ReadEvalPrintLoop.st
branchjv
changeset 21024 8734987eb5c7
parent 19410 f9d7cb8bd74c
parent 20949 14f5982c2aee
equal deleted inserted replaced
20729:5a09e2a164af 21024:8734987eb5c7
    13 
    13 
    14 "{ NameSpace: Smalltalk }"
    14 "{ NameSpace: Smalltalk }"
    15 
    15 
    16 Object subclass:#ReadEvalPrintLoop
    16 Object subclass:#ReadEvalPrintLoop
    17 	instanceVariableNames:'inputStream outputStream errorStream compiler prompt
    17 	instanceVariableNames:'inputStream outputStream errorStream compiler prompt
    18 		doChunkFormat traceFlag timingFlag printFlag exitAction
    18 		doChunkFormat traceFlag timingFlag profilingFlag printFlag
    19 		currentDirectory'
    19 		exitAction currentDirectory lastEditedClass lastEditedSelector
       
    20 		editorCommand'
    20 	classVariableNames:''
    21 	classVariableNames:''
    21 	poolDictionaries:''
    22 	poolDictionaries:''
    22 	category:'System-Support'
    23 	category:'System-Support'
    23 !
    24 !
    24 
    25 
    40 
    41 
    41 documentation
    42 documentation
    42 "
    43 "
    43     A simple read-eval-print loop for non-GUI or stscript operation.
    44     A simple read-eval-print loop for non-GUI or stscript operation.
    44     Invoked, for example if stx is started with a --repl argument.
    45     Invoked, for example if stx is started with a --repl argument.
    45 .
    46 
    46     A line starting with '?' shows the usage message.
    47     A line starting with '?' shows the usage message.
    47     Lines starting with '#' are directives:
    48     Lines starting with '#' are directives:
    48 	#exit   - exit the rep-loop
    49         #exit   - exit the rep-loop
    49 
    50         type '?' to see more.
       
    51         
    50     The input can be in one of two formats:
    52     The input can be in one of two formats:
    51 	1) traditional chunk format (bang-separated chunks, bangs duplicated)
    53         1) traditional chunk format (bang-separated chunks, bangs duplicated)
    52 	  this is the traditional fileIn format, as generated by fileOut from the browser
    54           this is the traditional fileIn format, as generated by fileOut from the browser
    53 
    55 
    54 	2) interactive line mode. Chunks are any number of lines up to either an empty line or
    56         2) interactive line mode. Chunks are any number of lines up to either an empty line or
    55 	  a line ending in a period. This is more useful for an interactive REPL, where statements/expressions
    57           a line ending in a period. This is more useful for an interactive REPL, where statements/expressions
    56 	  are entered linewise by a user.
    58           are entered linewise by a user.
    57 
    59 
    58     The input can is switched to non-chunk format whenever a line with a '#' in the first column appears.
    60     The input can is switched to non-chunk format whenever a line with a '#' in the first column appears.
       
    61 
       
    62     Try it (but only if you have a console):
       
    63         Smalltalk readEvalPrintLoop
       
    64 
       
    65     [Author:]
       
    66         Claus Gittinger
    59 "
    67 "
    60 ! !
    68 ! !
    61 
    69 
    62 !ReadEvalPrintLoop methodsFor:'accessing'!
    70 !ReadEvalPrintLoop methodsFor:'accessing'!
    63 
    71 
    81     doChunkFormat := aBoolean.
    89     doChunkFormat := aBoolean.
    82 
    90 
    83     "Created: / 07-12-2006 / 18:24:04 / cg"
    91     "Created: / 07-12-2006 / 18:24:04 / cg"
    84 !
    92 !
    85 
    93 
       
    94 editorCommand
       
    95     |editor|
       
    96 
       
    97     (editor := editorCommand) isNil ifTrue:[
       
    98         editor := OperatingSystem getEnvironment:'STX_EDITOR'.
       
    99         editor isNil ifTrue:[
       
   100             editor := OperatingSystem getEnvironment:'EDITOR'.
       
   101             editor isNil ifTrue:[
       
   102                 OperatingSystem isMSWINDOWSlike ifTrue:[
       
   103                     editor := 'notepad'.
       
   104                 ] ifFalse:[
       
   105                     editor := 'vi'.
       
   106                 ].    
       
   107             ].    
       
   108         ].    
       
   109     ].
       
   110     ^ editor
       
   111 
       
   112     "Created: / 08-11-2016 / 22:45:22 / cg"
       
   113 !
       
   114 
    86 error:aStream
   115 error:aStream
    87     "assign an error stream"
   116     "assign an error stream"
    88 
   117 
    89     errorStream := aStream.
   118     errorStream := aStream.
    90 
   119 
   186     self cmd_setOrClear:lineStream to:false
   215     self cmd_setOrClear:lineStream to:false
   187 
   216 
   188     "Created: / 07-12-2006 / 19:04:50 / cg"
   217     "Created: / 07-12-2006 / 19:04:50 / cg"
   189 !
   218 !
   190 
   219 
       
   220 cmd_debug:lineStream
       
   221     MiniDebugger enter.
       
   222 !
       
   223 
       
   224 cmd_edit:lineStream
       
   225     "edit a class or selector in an external editor"
       
   226 
       
   227     |errStream classOrMethodName cls methodName selector 
       
   228      code isNewClass editFullClass tmpFile modifiedTime|
       
   229 
       
   230     errStream := self errorStream.
       
   231 
       
   232     isNewClass := editFullClass := false.
       
   233 
       
   234     lineStream skipSeparators.
       
   235     lineStream atEnd ifTrue:[
       
   236         cls := lastEditedClass.
       
   237         methodName := lastEditedSelector.
       
   238     ] ifFalse:[    
       
   239 
       
   240         classOrMethodName := lineStream 
       
   241                                 upToElementForWhich:[:ch | 
       
   242                                     ch isLetterOrDigit not and:[ch ~~ $_]
       
   243                                 ].
       
   244         "/ 
       
   245         (classOrMethodName isUppercaseFirst) ifTrue:[ 
       
   246             (cls := Smalltalk classNamed:classOrMethodName) isNil ifTrue:[
       
   247                 errStream show:'edit: no such class: ',classOrMethodName,' ; create (y/n)? '.
       
   248                 (self inputStream nextLine withoutSeparators startsWith:'y') ifFalse:[^ self].
       
   249                 isNewClass := true.
       
   250                 code := 
       
   251 '"/ change the code as required, then save and exit the editor.
       
   252 "/ To cancel this edit, leave the editor WITHOUT saving.
       
   253 "/
       
   254 
       
   255 Object
       
   256   subclass:#%1
       
   257   instanceVariableNames:''''
       
   258   classVariableNames:''''
       
   259   poolDictionaries:''''
       
   260   category:''user classes''
       
   261 '                   bindWith:classOrMethodName.
       
   262             ] ifFalse:[ 
       
   263                 lineStream skipSeparators.
       
   264                 lineStream atEnd ifFalse:[
       
   265                     methodName := lineStream upToSeparator.
       
   266                 ].
       
   267             ].
       
   268         ] ifFalse:[
       
   269             methodName := classOrMethodName   
       
   270         ].
       
   271     ].
       
   272     
       
   273     isNewClass ifFalse:[
       
   274         cls := cls ? lastEditedClass.
       
   275         cls isNil ifTrue:[
       
   276             errStream showCR:'edit usage:'.
       
   277             errStream showCR:'   #edit className selector'.
       
   278             errStream showCR:'   #edit className '.
       
   279             errStream showCR:'   #edit selector (class as in previous edit)'.
       
   280             errStream showCR:'   #edit          (class/method as in previous edit)'.
       
   281             ^ self.
       
   282         ].
       
   283         lastEditedClass := cls.
       
   284         lastEditedSelector := methodName.
       
   285 
       
   286         methodName isNil ifTrue:[
       
   287             editFullClass := true.
       
   288             code := cls source asString
       
   289         ] ifFalse:[    
       
   290             ((selector := methodName asSymbolIfInterned) isNil 
       
   291             or:[ (cls implements:selector) not]) ifTrue:[
       
   292                 errStream show:('"',methodName,'" is a new method; create (y/n)? ').
       
   293                 (self inputStream nextLine withoutSeparators startsWith:'y') ifFalse:[^ self].
       
   294                 code := 
       
   295 '"/ change the code as required, then save and exit the editor.
       
   296 "/ To cancel this edit, leave the editor WITHOUT saving.
       
   297 
       
   298 %1
       
   299     "this is a new method"
       
   300     self halt
       
   301 '                   bindWith:methodName.
       
   302             ] ifFalse:[
       
   303                 code := (cls compiledMethodAt:selector) source.
       
   304             ].    
       
   305         ].    
       
   306     ].
       
   307 
       
   308     [
       
   309         |ok cmd|
       
   310 
       
   311         tmpFile := Filename newTemporary.
       
   312         tmpFile contents:code.
       
   313         modifiedTime := tmpFile modificationTime.
       
   314 
       
   315         cmd := '%1 "%2"'.
       
   316         OperatingSystem isUNIXlike ifTrue:[
       
   317             cmd := '%1 "%2" </dev/tty'.
       
   318         ].
       
   319         
       
   320         ok := OperatingSystem 
       
   321                 executeCommand:(cmd bindWith:(self editorCommand) with:tmpFile pathName)
       
   322                 inputFrom:Stdin 
       
   323                 outputTo:Stdout 
       
   324                 errorTo:Stderr
       
   325                 auxFrom:nil
       
   326                 environment:nil
       
   327                 inDirectory:nil
       
   328                 lineWise:false
       
   329                 newPgrp:false
       
   330                 showWindow:true
       
   331                 onError:[:status | false].
       
   332                 
       
   333         (ok and:[tmpFile modificationTime ~= modifiedTime]) ifTrue:[
       
   334             isNewClass ifTrue:[
       
   335                 Compiler evaluate:tmpFile contentsOfEntireFile.    
       
   336                 errStream showCR:'Class (re)defined.'
       
   337             ] ifFalse:[
       
   338                 editFullClass ifTrue:[
       
   339                     tmpFile fileIn.
       
   340                     errStream showCR:'Class (re)compiled.'
       
   341                 ] ifFalse:[    
       
   342                     cls compile:tmpFile contentsOfEntireFile classified:'*as yet uncategorized'.    
       
   343                     errStream showCR:'Method (re)compiled.'
       
   344                 ].    
       
   345             ].    
       
   346         ] ifFalse:[
       
   347             errStream showCR:'No change.'
       
   348         ].    
       
   349     ] ensure:[
       
   350         tmpFile notNil ifTrue:[
       
   351             tmpFile remove
       
   352         ]
       
   353     ].
       
   354     
       
   355     "
       
   356      Smalltalk readEvalPrintLoop
       
   357 
       
   358      self new 
       
   359         input:Stdin;
       
   360         cmd_edit:'MyClass foo' readStream
       
   361     "
       
   362 
       
   363     "Modified: / 08-11-2016 / 22:46:12 / cg"
       
   364 !
       
   365 
   191 cmd_exit:lineStream
   366 cmd_exit:lineStream
   192     exitAction value
   367     exitAction value
   193 
   368 
   194     "Created: / 07-12-2006 / 18:55:46 / cg"
   369     "Created: / 07-12-2006 / 18:55:46 / cg"
   195 !
   370 !
   196 
   371 
   197 cmd_help:lineStream
   372 cmd_help:lineStream
   198     self errorStream
   373     self errorStream
   199 	nextPutAll:
   374         nextPutAll:
   200 'Everything entered up to an empty line or a line ending in "." is called a "chunk" and evaluated.
   375 'Everything entered up to an empty line or a line ending in "." is called a "chunk" and evaluated.
   201 Lines starting with "#" are commands to the read-eval-print interpreter.
   376 Lines starting with "#" are commands to the read-eval-print interpreter.
   202 
   377 
   203 Valid commands are:
   378 Valid commands are:
   204     #help ............... this text
   379     #help ............... this text
   205     #exit ............... exit interpreter loop
   380     #exit ............... exit interpreter loop
   206     #use <package>....... use (load) a package
   381     #use <package>....... use (load) a package
   207 	stx:libwidg .............. GUI package
   382         stx:libwidg .............. GUI package
   208 	stx:libtool .............. IDE tool package
   383         stx:libtool .............. IDE tool package
   209 	stx:goodies/regex ........ regex package
   384         stx:goodies/regex ........ regex package
   210 	stx:goodies/petitparser .. peg parser package
   385         stx:goodies/petitparser .. peg parser package
   211     #read <filename>..... read another script or source file
   386     #read <filename>..... read another script or source file
   212     #show <what> ........ show info
   387     #show <what> ........ show info
   213 	variables .......... interpreter variables
   388         variables .......... interpreter variables
   214 	processes .......... processes
   389         processes .......... processes
   215 	memory ............. memory usage
   390         memory ............. memory usage
   216 	flags .............. flags
   391         flags .............. flags
   217 	modules ............ loaded modules
   392         modules ............ loaded modules
       
   393         packages ........... available packages to load
       
   394         all ................ all of the above
   218     #set/clear <flag> ... set or clear a flag
   395     #set/clear <flag> ... set or clear a flag
   219 	trace .............. tracing execution
   396         trace .............. tracing execution
   220 	timing ............. timing execution
   397         timing ............. timing execution
   221 	chunkFormat ........ traditional bang chunk format input mode
   398         profiling .......... show execution profile
       
   399         chunkFormat ........ traditional bang chunk format input mode
       
   400         editor ............. command used with #edit directive
       
   401     #debug ................. enter a MiniDebugger
       
   402     #edit <what> ........ open an external editor 
       
   403         class .............. on a class
       
   404         class selector ..... on a method
       
   405         <empty> ............ on previously edited method/last class
   222 
   406 
   223 The MiniDebugger (if entered) shows its own help with "?".
   407 The MiniDebugger (if entered) shows its own help with "?".
   224 '
   408 '
   225 
   409 
   226     "Created: / 07-12-2006 / 18:54:20 / cg"
   410     "Created: / 07-12-2006 / 18:54:20 / cg"
       
   411     "Modified: / 08-11-2016 / 22:53:53 / cg"
   227 !
   412 !
   228 
   413 
   229 cmd_read:lineStream
   414 cmd_read:lineStream
   230     |filename newInput savedPrompt savedPrint savedInput savedCurrentDirectory|
   415     |filename newInput savedPrompt savedPrint savedInput savedCurrentDirectory savedDoChunkFormat|
   231 
   416 
   232     lineStream skipSeparators.
   417     lineStream skipSeparators.
   233     filename := lineStream upToEnd withoutSeparators.
   418     filename := lineStream upToEnd withoutSeparators.
   234     filename isNil ifTrue:[
   419     filename isNil ifTrue:[
   235 	'? which file?' errorPrintCR.
   420         self errorStream showCR:'? which file?'.
   236 	^ self.
   421         ^ self.
   237     ].
   422     ].
   238     filename := filename withoutSeparators.
   423     filename := filename withoutSeparators.
   239     filename isEmpty ifTrue:[
   424     filename isEmpty ifTrue:[
   240 	'? which file?' errorPrintCR.
   425         self errorStream showCR:'? which file?'.
   241 	^ self.
   426         ^ self.
   242     ].
   427     ].
       
   428 
       
   429     currentDirectory := currentDirectory ? (Filename currentDirectory).
   243 
   430 
   244     filename := filename asFilename.
   431     filename := filename asFilename.
   245     filename isAbsolute ifFalse:[
   432     filename isAbsolute ifFalse:[
   246 	filename := currentDirectory construct:filename.
   433         filename := currentDirectory construct:filename.
   247     ].
   434     ].
   248 
   435 
   249     newInput := filename readStream.
   436     StreamError ignoreIn:[
       
   437         newInput := filename readStream.
       
   438     ].
   250     newInput isNil ifTrue:[
   439     newInput isNil ifTrue:[
   251 	('Could not find file: "',filename,'"') errorPrintCR.
   440         self errorStream showCR:('Could not find file: "',filename pathName,'"').
   252 	^ self.
   441         ^ self.
   253     ].
   442     ].
   254 
   443 
   255     [
   444     [
   256 	savedCurrentDirectory := currentDirectory.
   445         savedCurrentDirectory := currentDirectory.
   257 	savedInput := inputStream.
   446         savedDoChunkFormat := doChunkFormat.
   258 	savedPrint := printFlag.
   447         savedInput := inputStream.
   259 	savedPrompt := prompt.
   448         savedPrint := printFlag.
   260 
   449         savedPrompt := prompt.
   261 	currentDirectory := filename directory.
   450 
   262 	inputStream := newInput.
   451         currentDirectory := filename directory.
   263 
   452         inputStream := newInput.
   264 	self
   453         
   265 	    basicReadEvalPrintLoopWithInput:newInput
   454         self
   266 	    output:outputStream
   455             basicReadEvalPrintLoopWithInput:newInput
   267 	    error:errorStream
   456             output:outputStream
   268 	    compiler:compiler
   457             error:errorStream
   269 	    prompt:false
   458             compiler:(compiler ? Compiler ? Parser)
   270 	    print:false.
   459             prompt:false
       
   460             print:false.
   271     ] ensure:[
   461     ] ensure:[
   272 	currentDirectory := savedCurrentDirectory.
   462         newInput close.
   273 	inputStream := savedInput.
   463         doChunkFormat := savedDoChunkFormat.
   274 	printFlag := savedPrint.
   464         currentDirectory := savedCurrentDirectory.
   275 	prompt := savedPrompt
   465         inputStream := savedInput.
       
   466         printFlag := savedPrint.
       
   467         prompt := savedPrompt.
   276     ].
   468     ].
   277 !
   469 !
   278 
   470 
   279 cmd_set:lineStream
   471 cmd_set:lineStream
   280     self cmd_setOrClear:lineStream to:true
   472     self cmd_setOrClear:lineStream to:true
   286     |what|
   478     |what|
   287 
   479 
   288     lineStream skipSeparators.
   480     lineStream skipSeparators.
   289     what := lineStream nextAlphaNumericWord.
   481     what := lineStream nextAlphaNumericWord.
   290     what notNil ifTrue:[
   482     what notNil ifTrue:[
   291 	(what startsWith:'tra') ifTrue:[
   483         (what startsWith:'tra') ifTrue:[
   292 	    traceFlag := aBoolean.
   484             traceFlag := aBoolean.
   293 	    ^ self.
   485             ^ self.
   294 	].
   486         ].
   295 	(what startsWith:'tim') ifTrue:[
   487         (what startsWith:'tim') ifTrue:[
   296 	    timingFlag := aBoolean.
   488             timingFlag := aBoolean.
   297 	    ^ self.
   489             ^ self.
   298 	].
   490         ].
   299 	(what startsWith:'chunk') ifTrue:[
   491         (what startsWith:'pro') ifTrue:[
   300 	    doChunkFormat := aBoolean.
   492             profilingFlag := aBoolean.
   301 	    ^ self.
   493             ^ self.
   302 	].
   494         ].
   303     ].
   495         (what startsWith:'chunk') ifTrue:[
   304     self errorStream nextPutLine:'? which flag ?'.
   496             doChunkFormat := aBoolean.
   305 
   497             ^ self.
   306     "Modified: / 07-12-2006 / 19:13:34 / cg"
   498         ].
       
   499         (what startsWith:'edi') ifTrue:[
       
   500             aBoolean ifTrue:[
       
   501                 "/ set editor cmd
       
   502                 lineStream skipSeparators.
       
   503                 editorCommand := lineStream upToEnd.
       
   504             ] ifFalse:[
       
   505                 editorCommand := nil.
       
   506             ].
       
   507             ^ self.
       
   508         ].
       
   509     ].
       
   510     self errorStream showCR:'? which flag ?'.
       
   511 
       
   512     "Modified: / 08-11-2016 / 22:49:17 / cg"
   307 !
   513 !
   308 
   514 
   309 cmd_show:lineStream
   515 cmd_show:lineStream
   310     |errStream what all printModule|
   516     |errStream what showAll ok|
   311 
   517 
   312 "
       
   313  self basicNew cmd_show:'packages' readStream
       
   314 "
       
   315     errStream := self errorStream.
   518     errStream := self errorStream.
   316 
   519 
   317     lineStream skipSeparators.
   520     lineStream skipSeparators.
   318     what := lineStream nextAlphaNumericWord.
   521     what := lineStream nextAlphaNumericWord.
       
   522     ok := false.
       
   523     
   319     what notNil ifTrue:[
   524     what notNil ifTrue:[
   320 	(what startsWith:'var') ifTrue:[
   525         showAll := (what startsWith:'all').
   321 	    Workspace notNil ifTrue:[
   526         
   322 		Workspace workspaceVariables keysAndValuesDo:[:nm :h |
   527         (showAll or:[ what startsWith:'var' ]) ifTrue:[                      
   323 		    errStream nextPutAll:nm; nextPutAll:' -> '; nextPutLine:h value.
   528             showAll ifTrue:[ errStream showCR:'Variables:'; showCR:'----------' ].
   324 		].
   529             self showVariables.
   325 	    ].
   530             ok := true.
   326 	    ^ self.
   531         ].
   327 	].
   532         
   328 	(what startsWith:'proc') ifTrue:[
   533         (showAll or:[ what startsWith:'proc' ]) ifTrue:[                    
   329 	    MiniDebugger basicNew showProcesses.
   534             showAll ifTrue:[ errStream cr; showCR:'Threads:'; showCR:'--------' ].
   330 	    ^ self.
   535             MiniDebugger basicNew showProcesses.
   331 	].
   536             ok := true.
   332 	(what startsWith:'mod') ifTrue:[
   537         ].
   333 	    printModule :=
   538         
   334 		[:mod |
   539         ("showAll or:[" what startsWith:'pack' "]") ifTrue:[                    
   335 		    errStream
   540             showAll ifTrue:[ errStream cr; showCR:'Available Packages:'; showCR:'--------' ].
   336 			nextPutAll:'  ';
   541             self showPackages.
   337 			nextPutAll:(mod package "libraryName");
   542             ok := true.
   338 			nextPutLine:' (',(mod type),')'.
   543         ].
   339 		].
   544 
   340 
   545         (showAll or:[ what startsWith:'mod' ]) ifTrue:[
   341 	    errStream nextPutLine:'builtIn:'.
   546             showAll ifTrue:[ errStream cr; showCR:'Modules:'; showCR:'--------' ].
   342 	    ((ObjectMemory binaryModuleInfo
   547             self showModules.
   343 		reject:[:m | m dynamic])
   548 
   344 		    asSortedCollection:[:a :b | a name < b name]) do:printModule.
   549             ok := true.
   345 
   550         ].
   346 	    errStream nextPutLine:'dynamic:'.
   551         
   347 	    ((ObjectMemory binaryModuleInfo
   552         (showAll or:[ what startsWith:'mem' ]) ifTrue:[
   348 		select:[:m | m dynamic])
   553             |allMem|
   349 		    asSortedCollection:[:a :b | a name < b name]) do:printModule.
   554             
   350 
   555             showAll ifTrue:[ errStream cr; showCR:'Memory:'; showCR:'-------' ].
   351 	    ^ self.
   556             "/ allMem := ObjectMemory oldSpaceUsed + ObjectMemory symSpaceUsed
   352 	].
   557             "/                                     + ObjectMemory newSpaceUsed.
   353 	(what startsWith:'mem') ifTrue:[
   558             errStream
   354 	    all := ObjectMemory oldSpaceUsed + ObjectMemory symSpaceUsed
   559                 "/ showCR:('overall: ',(allMem // 1024) printString,' Kb');
   355 					     + ObjectMemory newSpaceUsed.
   560                 showCR:('used   : ',(ObjectMemory bytesUsed // 1024) printString,' Kb');
   356 	    errStream
   561                 showCR:('free   : ',(ObjectMemory freeSpace // 1024) printString,' Kb');
   357 		nextPutLine:('overall: ',(all // 1024) printString,' Kb');
   562                 show:('minorGC: ',(ObjectMemory scavengeCount) printString);
   358 		nextPutLine:('in use : ',(ObjectMemory bytesUsed // 1024) printString,' Kb');
   563                 showCR:(' majorGC: ',(ObjectMemory garbageCollectCount) printString).
   359 		nextPutLine:('free   : ',(ObjectMemory freeSpace // 1024) printString,' Kb');
   564             ok := true.
   360 		nextPutLine:('minorGC: ',(ObjectMemory scavengeCount) printString);
   565         ].
   361 		nextPutLine:('majorGC: ',(ObjectMemory garbageCollectCount) printString).
   566         
   362 	    ^ self.
   567         (showAll or:[ what startsWith:'flag' ]) ifTrue:[
   363 	].
   568             showAll ifTrue:[ errStream cr; showCR:'Flags:'; showCR:'------' ].
   364 	(what startsWith:'flag') ifTrue:[
   569             errStream
   365 	    errStream
   570                 showCR:('trace :      ',(traceFlag ? false) printString);
   366 		nextPutLine:('trace :      ',traceFlag printString);
   571                 showCR:('timing:      ',(timingFlag ? false) printString);
   367 		nextPutLine:('timing:      ',timingFlag printString);
   572                 showCR:('profiling:   ',(profilingFlag ? false) printString);
   368 		nextPutLine:('chunkFormat: ',doChunkFormat printString).
   573                 showCR:('chunkFormat: ',(doChunkFormat ? false) printString);
   369 	    ^ self.
   574                 showCR:('editor:      ',self editorCommand printString).
   370 	].
   575             ok := true.
   371     ].
   576         ].
   372 
   577     ].
   373     errStream nextPutLine:'? show what ?'.
   578 
   374 
   579     ok ifFalse:[
   375     "Modified: / 07-12-2011 / 22:15:07 / cg"
   580         errStream showCR:'? show what ?'.
       
   581     ].
       
   582     
       
   583     "
       
   584      self basicNew cmd_show:'packages' readStream
       
   585     "
       
   586 
       
   587     "Modified: / 08-11-2016 / 22:46:51 / cg"
   376 !
   588 !
   377 
   589 
   378 cmd_use:lineStream
   590 cmd_use:lineStream
   379     |pkg|
   591     |pkg|
   380 
   592 
   381     lineStream skipSeparators.
   593     lineStream skipSeparators.
   382     pkg := lineStream upToEnd.
   594     pkg := lineStream upToEnd.
   383     pkg isNil ifTrue:[
   595     pkg isNil ifTrue:[
   384 	'? which package?' errorPrintCR.
   596         self errorStream showCR:'? which package?'.
   385 	^ self.
   597         ^ self.
   386     ].
   598     ].
   387     pkg := pkg withoutSeparators.
   599     pkg := pkg withoutSeparators.
   388     pkg isEmpty ifTrue:[
   600     pkg isEmpty ifTrue:[
   389 	'? which package?' errorPrintCR.
   601         self errorStream showCR:'? which package?'.
   390 	^ self.
   602         ^ self.
   391     ].
   603     ].
   392 
   604 
   393     [
   605     [
   394 	Smalltalk loadPackage:pkg.
   606         Smalltalk loadPackage:pkg.
   395     ] on:PackageLoadError do:[:ex|
   607     ] on:PackageLoadError do:[:ex|
   396 	"/ allow for some shortcuts...
   608         "/ allow for some shortcuts...
   397 	(pkg includes:$:) ifTrue:[
   609         (pkg includes:$:) ifTrue:[
   398 	    self errorStream nextPutLine:('Failed to load package: "',pkg,'"').
   610             self errorStream showCR:('Failed to load package: "',pkg,'"').
   399 	] ifFalse:[
   611         ] ifFalse:[
   400 	    "/ try stx standard package
   612             "/ try stx standard package
   401 	    pkg := 'stx:', pkg.
   613             pkg := 'stx:', pkg.
   402 	    ex restart.
   614             ex restart.
   403 	].
   615         ].
   404     ].
   616     ].
   405 
   617 
   406     "Created: / 07-12-2006 / 19:07:56 / cg"
   618     "Created: / 07-12-2006 / 19:07:56 / cg"
   407 !
   619 !
   408 
   620 
   409 directive:line
   621 directive:line
   410     |s cmd|
   622     |s cmd|
   411 
   623 
   412     s := line readStream.
   624     s := line readStream.
   413     s next. "/ skip the hash
   625     s next. "/ skip the hash
       
   626     s peek == $!! ifTrue:[
       
   627         "/ skip shebang line 
       
   628         ^ self.
       
   629     ].    
   414     s skipSeparators.
   630     s skipSeparators.
   415 
   631 
   416     cmd := s nextAlphaNumericWord.
   632     cmd := s nextAlphaNumericWord.
   417     cmd notNil ifTrue:[
   633     cmd notNil ifTrue:[
   418 	self
   634         AbortAllOperationRequest handle:[:ex |
   419 	    perform:('cmd_',cmd) asMutator with:s
   635             self errorStream showCR:('Directive aborted: ', ex description)
   420 	    ifNotUnderstood:[
   636         ] do:[
   421 		self errorStream
   637             Error handle:[:ex |
   422 		    nextPutAll:'?? invalid command: ';
   638                 self errorStream showCR:('Caught in directive: ', ex description).
   423 		    nextPutAll:cmd;
   639                 ex suspendedContext fullPrintAll.
   424 		    nextPutAll:'. Type "#help" for help.';
   640             ] do:[    
   425 		    cr.
   641                 ControlInterrupt handle:[:ex |
   426 	    ].
   642                     MiniDebugger enter.
       
   643                     "/ self errorStream showCR:('Ignored in directive: ', ex description).
       
   644                     "/ ex reject. 
       
   645                     "/ ex proceed. 
       
   646                 ] do:[    
       
   647                     self
       
   648                         perform:('cmd_',cmd) asMutator with:s
       
   649                         ifNotUnderstood:[
       
   650                             self errorStream
       
   651                                 show:'?? invalid command: '; show:cmd;
       
   652                                 showCR:'. Type "#help" for help.'
       
   653                         ].
       
   654                 ].
       
   655             ].
       
   656         ].
   427     ].
   657     ].
   428 
   658 
   429     "Created: / 07-12-2006 / 18:49:17 / cg"
   659     "Created: / 07-12-2006 / 18:49:17 / cg"
       
   660     "Modified: / 08-11-2016 / 21:59:16 / cg"
       
   661 !
       
   662 
       
   663 showModules
       
   664     |errStream printModule|
       
   665 
       
   666     errStream := self errorStream.
       
   667     
       
   668     printModule :=
       
   669         [:mod |
       
   670             errStream
       
   671                 show:'  ';
       
   672                 show:(mod package "libraryName");
       
   673                 showCR:' (',(mod type),')'.
       
   674         ].
       
   675 
       
   676     errStream nextPutLine:'builtIn:'.
       
   677     ((ObjectMemory binaryModuleInfo
       
   678         reject:[:m | m dynamic])
       
   679             asSortedCollection:[:a :b | a name < b name]) do:printModule.
       
   680 
       
   681     errStream nextPutLine:'dynamic:'.
       
   682     ((ObjectMemory binaryModuleInfo
       
   683         select:[:m | m dynamic])
       
   684             asSortedCollection:[:a :b | a name < b name]) do:printModule.
       
   685 
       
   686     "
       
   687      ReadEvalPrintLoop basicNew showModules
       
   688     "
       
   689 !
       
   690 
       
   691 showPackages
       
   692     |all|
       
   693 
       
   694     all := Set new.
       
   695     Smalltalk knownLoadablePackagesDo:[:packageID :type :path |
       
   696         all add:packageID
       
   697     ].
       
   698     all := all asOrderedCollection sort.
       
   699     all do:[:eachPackage |
       
   700         self errorStream show:eachPackage.
       
   701         (Smalltalk isPackageLoaded:eachPackage) ifTrue:[
       
   702             self errorStream show:' (loaded)'.
       
   703         ].    
       
   704         self errorStream cr.
       
   705     ].    
       
   706 
       
   707     "
       
   708      ReadEvalPrintLoop basicNew showPackages
       
   709      ReadEvalPrintLoop basicNew showModules
       
   710     "
       
   711 !
       
   712 
       
   713 showVariables
       
   714     Workspace notNil ifTrue:[
       
   715         Workspace workspaceVariables keys asOrderedCollection sort do:[:nm |
       
   716             |holder|
       
   717             holder := Workspace workspaceVariables at:nm.
       
   718             self errorStream 
       
   719                 show:nm;  
       
   720                 show:' -> '; 
       
   721                 showCR:holder value printString.
       
   722         ].
       
   723     ].
       
   724 
       
   725     "
       
   726      ReadEvalPrintLoop basicNew showVariables
       
   727     "
   430 ! !
   728 ! !
   431 
   729 
   432 !ReadEvalPrintLoop methodsFor:'evaluation'!
   730 !ReadEvalPrintLoop methodsFor:'evaluation'!
   433 
   731 
   434 basicReadEvalPrintLoopWithInput:input output:output error:error
   732 basicReadEvalPrintLoopWithInput:input output:output error:error
   438 
   736 
   439     "the core of the interpreter loop; extracted and parametrized, so it can be called recursive
   737     "the core of the interpreter loop; extracted and parametrized, so it can be called recursive
   440      for included scripts.
   738      for included scripts.
   441      If chunkFormat is true, chunks are read.
   739      If chunkFormat is true, chunks are read.
   442      Otherwise, lines up to an empty line (or EOF) or a line ending in '.' are read.
   740      Otherwise, lines up to an empty line (or EOF) or a line ending in '.' are read.
   443      A '#' character appearing in the first column of the first line turns off chunkmode."
   741      A '#' character appearing in the first column of the first line turns off chunkmode,
       
   742      which allows for convenient shell scripts containing a #/bin/stx as the first line."
       
   743 
       
   744     exitAction := [^ self].
   444 
   745 
   445     [
   746     [
   446 	|lines chunk|
   747         |lines chunk|
   447 
   748 
   448 	prompt notNil ifTrue:[
   749         prompt notNil ifTrue:[
   449 	    error nextPutAll:prompt.
   750             error show:prompt.
   450 	].
   751         ].
   451 
   752 
   452 	input atEnd ifTrue:[
   753         input atEnd ifTrue:[
   453 	    error cr.
   754             doPrint ifTrue:[ error cr ].
   454 	    ^ self.
   755             ^ self.
   455 	].
   756         ].
   456 
   757 
   457 	input peek == $# ifTrue:[
   758         input peek == $# ifTrue:[
   458 	    self doChunkFormat:false.
   759             self doChunkFormat:false.
   459 	].
   760         ].
   460 
   761 
   461 	self doChunkFormat ifTrue:[
   762         self doChunkFormat ifTrue:[
   462 	    input skipSeparators.
   763             input skipSeparators.
   463 	    chunk := input nextChunk.
   764             chunk := input nextChunk.
   464 	] ifFalse:[
   765         ] ifFalse:[
   465 	    lines := OrderedCollection new.
   766             lines := OrderedCollection new.
   466 	    [
   767             [
   467 		|line|
   768                 |line|
   468 
   769 
   469 		line := input nextLine.
   770                 line := input nextLine.
   470 		line notEmptyOrNil ifTrue:[
   771                 line notEmptyOrNil ifTrue:[
   471 		    line = '?' ifTrue:[
   772                     line = '?' ifTrue:[
   472 			self cmd_help:nil.
   773                         self cmd_help:nil.
   473 			prompt notNil ifTrue:[
   774                         prompt notNil ifTrue:[
   474 			    error nextPutAll:prompt.
   775                             error show:prompt.
   475 			].
   776                         ].
   476 		    ] ifFalse:[
   777                     ] ifFalse:[
   477 			(line startsWith:'#') ifTrue:[
   778                         (line startsWith:'#') ifTrue:[
   478 			    self directive:line.
   779                             self directive:line.
   479 			    prompt notNil ifTrue:[
   780                             prompt notNil ifTrue:[
   480 				error nextPutAll:prompt.
   781                                 error show:prompt.
   481 			    ].
   782                             ].
   482 			] ifFalse:[
   783                         ] ifFalse:[
   483 			    lines add:line.
   784                             lines add:line.
   484 			]
   785                         ]
   485 		    ]
   786                     ]
   486 		].
   787                 ].
   487 		line notEmptyOrNil and:[(line endsWith:$.) not].
   788                 line notEmptyOrNil and:[(line endsWith:$.) not].
   488 	    ] whileTrue.
   789             ] whileTrue.
   489 	    chunk := lines asStringWith:Character cr.
   790             chunk := lines asStringWith:Character cr.
   490 	].
   791         ].
   491 
   792 
   492 	(chunk notEmptyOrNil and:[chunk withoutSeparators notEmpty]) ifTrue:[
   793         (chunk notEmptyOrNil 
   493 	    "abortAll is handled, but not asked for here!!"
   794           and:[chunk withoutSeparators notEmpty
   494 	    AbortAllOperationRequest handle:[:ex |
   795           and:[chunk withoutSeparators ~= '.']]
   495 		error nextPutLine:('Evaluation aborted: ', ex description)
   796         ) ifTrue:[
   496 	    ] do:[
   797             "abortAll is handled, but not asked for here!!"
   497 		(Error, ControlInterrupt) handle:[:ex |
   798             AbortAllOperationRequest handle:[:ex |
   498 		    prompt isNil ifTrue:[
   799                 error nextPutLine:('Evaluation aborted: ', ex description)
   499 			ex reject
   800             ] do:[
   500 		    ].
   801                 (Error, ControlInterrupt) handle:[:ex |
   501 		    MiniDebugger enterWithMessage:(ex errorString) mayProceed:true.
   802                     prompt isNil ifTrue:[
   502 		    ex mayProceed ifTrue:[
   803                         ex reject
   503 			ex proceed.
   804                     ].
   504 		    ].
   805                     MiniDebugger enterWithMessage:(ex errorString) mayProceed:true.
   505 		    error nextPutLine:('Evaluation aborted: ', ex description).
   806                     ex mayProceed ifTrue:[
   506 		    ex return.
   807                         ex proceed.
   507 		] do:[
   808                     ].
   508 		    |value ms us|
   809                     error showCR:('Evaluation aborted: ', ex description).
   509 
   810                     ex return.
   510 		    ms := Time millisecondsToRun:[
   811                 ] do:[
   511 			us := Time microsecondsToRun:[
   812                     |value ms us|
   512 			    value := (compilerClass new
   813 
   513 					requestor:self)
   814                     profilingFlag == true ifTrue:[ 
   514 					evaluate:chunk
   815                         MessageTally spyDetailedOn:[
   515 					compile:true.
   816                             value := (compilerClass new requestor:self) 
   516 			].
   817                                         evaluate:chunk
   517 		    ].
   818                                         compile:true.
   518 		    doPrint ifTrue:[
   819                         ].    
   519 			value printOn:output. output cr.
   820                         doPrint ifTrue:[
   520 		    ].
   821                             value printOn:output. output cr.
   521 
   822                             output flush.
   522 		    timingFlag == true ifTrue:[
   823                         ].
   523 			'execution time: ' printOn:error.
   824                     ] ifFalse:[    
   524 			ms < 1 ifTrue:[
   825                         us := Time microsecondsToRun:[
   525 			    us < 1 ifTrue:[
   826                             value := (compilerClass new requestor:self)
   526 				'too small to measure (<1us)' printOn:error.
   827                                         evaluate:chunk compile:true.
   527 			    ] ifFalse:[
   828                         ].
   528 				us printOn:output. 'us' printOn:error.
   829                         doPrint ifTrue:[
   529 			    ]
   830                             value isVoid ifFalse:[
   530 			] ifFalse:[
   831                                 value printOn:output. output cr.
   531 			    ms printOn:output. 'ms' printOn:error.
   832                             ].
   532 			].
   833                         ].
   533 			error cr.
   834 
   534 		    ].
   835                         timingFlag == true ifTrue:[
   535 		    Workspace notNil ifTrue:[
   836                             'execution time: ' printOn:error.
   536 			Workspace workspaceVariableAt:'_$$' put:value.
   837                             us < 1000 ifTrue:[
   537 		    ].
   838                                 us < 1 ifTrue:[
   538 		].
   839                                     'too small to measure (<1us)' printOn:error.
   539 	    ].
   840                                 ] ifFalse:[
   540 	].
   841                                     us printOn:output. 'us' printOn:error.
       
   842                                 ]
       
   843                             ] ifFalse:[
       
   844                                 ((us / 1000) asFixedPoint:2) printOn:output. 'ms' printOn:error.
       
   845                             ].
       
   846                             error cr.
       
   847                         ].
       
   848                     ].
       
   849                     Workspace notNil ifTrue:[
       
   850                         Workspace rememberResultAsWorkspaceVariable:value.
       
   851                     ].
       
   852                 ].
       
   853             ].
       
   854         ].
   541     ] loop.
   855     ] loop.
   542 
   856 
   543     "
   857     "
       
   858      Smalltalk readEvalPrintLoop.
       
   859 
   544      (ReadEvalPrintLoop new prompt:'>') readEvalPrintLoop
   860      (ReadEvalPrintLoop new prompt:'>') readEvalPrintLoop
   545     "
   861     "
   546 
   862 
   547     "Created: / 07-12-2006 / 17:27:21 / cg"
   863     "Created: / 07-12-2006 / 17:27:21 / cg"
   548     "Modified: / 06-12-2011 / 15:29:03 / cg"
   864     "Modified: / 08-11-2016 / 22:41:47 / cg"
   549 !
   865 !
   550 
   866 
   551 readEvalPrintLoop
   867 readEvalPrintLoop
   552     "{ Pragma: +optSpace }"
   868     "{ Pragma: +optSpace }"
   553 
   869 
   555      If the chunkFormat-argument is true, chunks are read.
   871      If the chunkFormat-argument is true, chunks are read.
   556      Otherwise, lines up to an empty line (or EOF) are read.
   872      Otherwise, lines up to an empty line (or EOF) are read.
   557      A '#' character appearing in the first column of the first line
   873      A '#' character appearing in the first column of the first line
   558      switches to chunkmode."
   874      switches to chunkmode."
   559 
   875 
   560     exitAction := [^ self].
       
   561 
       
   562     ControlInterrupt handle:[:ex |
   876     ControlInterrupt handle:[:ex |
   563 	self errorStream nextPutLine:('Caught: ', ex description).
   877         self errorStream showCR:('Caught: ', ex description).
   564 	ex restart.
   878         self inputStream atEnd ifTrue:[
       
   879             ex return.
       
   880         ].    
       
   881         MiniDebugger enter.
       
   882         ex proceed.
       
   883         "/ ex restart.
   565     ] do:[
   884     ] do:[
   566 	|input output error compilerClass|
   885         |input output error compilerClass|
   567 
   886 
   568 	"/ re-evaluate these in the loop, so they can be changed dynamically
   887         "/ re-evaluate these in the loop, so they can be changed dynamically
   569 	input := self inputStream.
   888         input := self inputStream.
   570 	output := self outputStream.
   889         output := self outputStream.
   571 	error := self errorStream.
   890         error := self errorStream.
   572 
   891 
   573 	compilerClass := compiler ? Compiler ? Parser.
   892         compilerClass := compiler ? Compiler ? Parser.
   574 	compilerClass isNil ifTrue:[
   893         compilerClass isNil ifTrue:[
   575 	    self errorStream nextPutLine:('oops - no Compiler class found').
   894             error showCR:('oops - no Compiler class found').
   576 	    ^ self.
   895             ^ self.
   577 	].
   896         ].
   578 	self
   897         StreamError handle:[:ex |
   579 	    basicReadEvalPrintLoopWithInput:input output:output error:error
   898             (input isOpen not or:[input atEnd]) ifTrue:[
   580 	    compiler:compilerClass prompt:prompt print:(printFlag ? true).
   899                 error showCR:'EOF on input'.
   581     ]
   900                 ex return.
   582 
   901             ].    
   583     "
   902             (output isOpen not) ifTrue:[
       
   903                 error showCR:'no output'.
       
   904             ].    
       
   905             (error isOpen not) ifTrue:[
       
   906             ].    
       
   907         ] do:[    
       
   908             input signalAtEnd:true.
       
   909             self
       
   910                 basicReadEvalPrintLoopWithInput:input output:output error:error
       
   911                 compiler:compilerClass prompt:prompt print:(printFlag ? true).
       
   912         ]
       
   913     ].
       
   914     "/ self errorStream showCR:('done.').
       
   915 
       
   916     "
       
   917      Stdin atEnd 
       
   918      Stdin clearEOF
       
   919      Smalltalk readEvalPrintLoop
   584      (ReadEvalPrintLoop new prompt:'>') readEvalPrintLoop
   920      (ReadEvalPrintLoop new prompt:'>') readEvalPrintLoop
   585     "
   921     "
   586 
   922 
   587     "Created: / 07-12-2006 / 17:27:21 / cg"
   923     "Created: / 07-12-2006 / 17:27:21 / cg"
   588     "Modified: / 06-12-2011 / 15:29:03 / cg"
   924     "Modified: / 08-11-2016 / 22:42:21 / cg"
   589 ! !
   925 ! !
   590 
   926 
   591 !ReadEvalPrintLoop methodsFor:'queries'!
   927 !ReadEvalPrintLoop methodsFor:'queries'!
   592 
   928 
   593 autoDefineVariables
   929 autoDefineVariables