Block.st
branchjv
changeset 25383 5d948c667c55
parent 23107 40173e082cbc
--- a/Block.st	Sat Jan 25 21:55:08 2020 +0000
+++ b/Block.st	Wed May 20 18:34:29 2020 +0100
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
 "
  COPYRIGHT (c) 1989 by Claus Gittinger
  COPYRIGHT (c) 2015 Jan Vrany
@@ -17,7 +19,7 @@
 
 CompiledCode variableSubclass:#Block
 	instanceVariableNames:'home nargs sourcePos initialPC'
-	classVariableNames:'InvalidNewSignal'
+	classVariableNames:''
 	poolDictionaries:''
 	category:'Kernel-Methods'
 !
@@ -88,9 +90,9 @@
         coll do:[:eachElement | Transcript showCR:eachElement ].
     
     Blocks keep a reference to the context where it was declared -
-    this allows blocks to access the methods arguments and/or variables.
+    this allows blocks to access the method's arguments and/or variables.
     This is still true after the method has returned - since the
-    block keeps this reference, the methods context will NOT die in this case.
+    block keeps this reference, the method's context will NOT die in this case.
     (for experts: Smalltalk blocks are technically lambdas/closures)
 
     A return (via ^-statement) out of a block will force a return from the
@@ -337,20 +339,6 @@
 "
 ! !
 
-!Block class methodsFor:'initialization'!
-
-initialize
-    "create signals raised by various errors"
-
-    InvalidNewSignal isNil ifTrue:[
-	InvalidNewSignal := Error newSignalMayProceed:false.
-	InvalidNewSignal nameClass:self message:#invalidNewSignal.
-	InvalidNewSignal notifierString:'blocks are only created by the system'.
-    ]
-
-    "Modified: 22.4.1996 / 16:34:20 / cg"
-! !
-
 !Block class methodsFor:'instance creation'!
 
 byteCode:bCode numArgs:numArgs numStack:nStack sourcePosition:sourcePos initialPC:initialPC literals:literals
@@ -365,17 +353,15 @@
     "create a new cheap (homeless) block.
      Not for public use - this is a special hook for the compiler."
 
-    |newBlock|
-
-    newBlock := (super basicNew:(literals size))
+    ^ (self basicNew:literals size)
 			   byteCode:bCode
 			   numArgs:numArgs
 			   numVars:numVars
 			   numStack:nStack
 		     sourcePosition:sourcePos
 			  initialPC:initialPC
-			   literals:literals.
-    ^ newBlock
+                   literals:literals; 
+        yourself.
 
     "Modified: 24.6.1996 / 12:36:48 / stefan"
     "Created: 13.4.1997 / 00:04:09 / cg"
@@ -386,13 +372,13 @@
      If you really need a block (assuming, you are some compiler),
      use basicNew and setup the instance carefully"
 
-    ^ InvalidNewSignal raise.
+    ^ MethodNotAppropriateError raiseErrorString:'blocks are only created by the system'.
 !
 
 new:size
     "catch creation of blocks - only the system creates blocks"
 
-    ^ InvalidNewSignal raise.
+    ^ MethodNotAppropriateError raiseErrorString:'blocks are only created by the system'.
 ! !
 
 !Block class methodsFor:'queries'!
@@ -407,6 +393,7 @@
 ! !
 
 
+
 !Block methodsFor:'Compatibility-ANSI'!
 
 argumentCount
@@ -532,7 +519,7 @@
     "activate the receiver with one or zero arguments.
      Squeak compatibility, but also present in VW Smalltalk"
 
-    nargs >= 1 ifTrue:[^ self value:optionalFirstArg].
+    nargs > 0 ifTrue:[^ self value:optionalFirstArg].
     ^ self value
 !
 
@@ -541,7 +528,7 @@
      Squeak compatibility, but also present in VW Smalltalk"
 
     nargs >= 2 ifTrue:[^ self value:optionalFirstArg value:optionalSecondArg].
-    nargs = 1 ifTrue:[^ self value:optionalFirstArg].
+    nargs == 1 ifTrue:[^ self value:optionalFirstArg].
     ^ self value
 !
 
@@ -555,7 +542,7 @@
 	].
 	^ self value:optionalFirstArg value:optionalSecondArg
     ].
-    nargs = 1 ifTrue:[^ self value:optionalFirstArg].
+    nargs == 1 ifTrue:[^ self value:optionalFirstArg].
     ^ self value
 !
 
@@ -570,22 +557,14 @@
     |numArgs|
 
     numArgs := handlerBlock isBlock ifTrue:[handlerBlock argumentCount] ifFalse:[0].
-    numArgs == 1 ifTrue:[
+    numArgs <= 1 ifTrue:[
         ^ self on:Error do:handlerBlock
     ].
 
     ^ self
         on:Error
         do:[:ex |
-            |errString errReceiver|
-
-            numArgs == 0 ifTrue:[
-                ex return:handlerBlock value
-            ] ifFalse:[
-                errString := ex description.
-                errReceiver := ex suspendedContext receiver.
-                ex return:(handlerBlock value:errString value:errReceiver)
-            ].
+            ex return:(handlerBlock value:ex description value:ex suspendedContext receiver)
         ]
 
     "
@@ -608,6 +587,8 @@
      a := 0.
      [ 123 / a ] ifError:[self halt]
     "
+
+    "Modified: / 18-03-2017 / 18:19:20 / stefan"
 !
 
 timeToRun
@@ -712,7 +693,45 @@
     "Created: / 28-08-2010 / 14:41:15 / cg"
 ! !
 
-
+!Block methodsFor:'Javascript support'!
+
+_at:index
+    "this is a synthetic selector, generated by the compiler,
+     if a construct of the form expr[idx] is parsed.
+     I.e. 
+        foo[n]
+     generates
+        foo _at: n
+    "
+
+    ^ self value:index
+
+    "
+     |double|
+
+     double := [:n | n*2].
+     double[10]     
+    "
+!
+
+_at:index1 at:index2
+    "this is a synthetic selector, generated by the compiler,
+     if a construct of the form expr[idx] is parsed.
+     I.e. 
+        foo[n][m]
+     generates
+        foo _at:n at:m
+    "
+    ^ self value:index1 value:index2
+
+    "
+     |doubleDiv|
+
+     doubleDiv := [:n :d | n*2/d].
+     doubleDiv[10][3].     
+     doubleDiv[10 . 3].       
+    "
+! !
 
 !Block methodsFor:'accessing'!
 
@@ -747,9 +766,11 @@
 
     <resource: #obsolete>
 
+    self obsoleteMethodWarning:'use #homeMethod'.
     ^ self homeMethod
 
-    "Modified: 19.6.1997 / 16:15:24 / cg"
+    "Modified: / 19-06-1997 / 16:15:24 / cg"
+    "Modified: / 23-06-2017 / 10:47:00 / stefan"
 !
 
 methodHome
@@ -763,11 +784,11 @@
 !
 
 numArgs
+    <resource: #obsolete>  "/ but left in for a while, for performance and Squeak compatibility
+
     "return the number of arguments I expect for evaluation.
      Please use argumentCount for ANSI compatibility"
 
-"/    <resource: #obsolete>
-
     ^ nargs
 ! !
 
@@ -780,10 +801,34 @@
 
 !Block methodsFor:'conversion'!
 
+asBlock
+    ^ self
+
+    "Created: / 17-05-2019 / 15:09:21 / Claus Gittinger"
+!
+
+asIterator
+    "return myself as an iterator.
+     that is a collection which uses the receiver block to
+     generate the elements."
+
+    ^ Iterator on:self.
+
+    "
+     |coll|
+     
+     coll := [:action | 1 to:20 do:action] asIterator.
+     coll do:[:each | Transcript showCR:each].
+    "
+
+    "Created: / 09-02-2019 / 15:31:10 / Claus Gittinger"
+!
+
 asVarArgBlock
     "convert myself into a varArg block;
      this one has 1 formal argument, which gets the list
-     of actual arguments when evaluated."
+     of actual arguments when evaluated
+     (similar to rest arg in scheme)."
 
     nargs ~~ 1 ifTrue:[
 	self error:'vararg blocks must take exactly 1 argument - the arg list'.
@@ -805,8 +850,8 @@
      b value:'arg1' value:'arg2' value:'arg3' value:'arg4'
     "
 
-    "Created: 23.1.1997 / 13:35:28 / cg"
-    "Modified: 23.1.1997 / 13:35:48 / cg"
+    "Created: / 23-01-1997 / 13:35:28 / cg"
+    "Modified (comment): / 28-06-2019 / 12:37:23 / Claus Gittinger"
 !
 
 beCurryingBlock
@@ -858,6 +903,14 @@
 
     "Created: 23.1.1997 / 13:35:28 / cg"
     "Modified: 23.1.1997 / 13:35:48 / cg"
+!
+
+literalArrayEncoding
+    "I have none"
+
+    ^ nil
+
+    "Created: / 11-02-2019 / 16:50:58 / sr"
 ! !
 
 !Block methodsFor:'copying'!
@@ -881,11 +934,12 @@
 !Block methodsFor:'debugging'!
 
 benchmark:anInfoString
-    "evaluate myseld and show the timing info on Transcript"
+    "evaluate myself and show the timing info on Transcript"
 
     |startTime endTime startCycles endCycles overhead overheadCycles 
      micros millis cycles|
 
+    "/warmup before executing self
     startTime := OperatingSystem getMicrosecondTime.
     startCycles := OperatingSystem getCPUCycleCount.
     [123] value.
@@ -893,7 +947,7 @@
     endTime := OperatingSystem getMicrosecondTime.
     overhead := endTime - startTime.
     "/ just in case, the OS does not support cpu cycles
-    overheadCycles := endCycles - startCycles.
+    startCycles notNil ifTrue:[ overheadCycles := endCycles - startCycles ].
     
     startTime := OperatingSystem getMicrosecondTime.
     startCycles := OperatingSystem getCPUCycleCount.
@@ -902,13 +956,16 @@
     endTime := OperatingSystem getMicrosecondTime.
 
     micros := (endTime - startTime - overhead) max:0.
+    "/ just in case, the OS does not support cpu cycles
+    startCycles notNil ifTrue:[
     cycles := (endCycles - startCycles - overheadCycles) max:0. 
+    ].
     
     Transcript show:anInfoString.
     micros < 1000 ifTrue:[
         "/ too stupid: many fonts do not have a mu,
         "/ so I output it as us here.
-        Transcript show:micros; show:' s'.
+        Transcript show:micros; show:' µs'.
     ] ifFalse:[
         micros < 100000 ifTrue:[
             millis := (micros / 1000.0) asFixedPointRoundedToScale:2.
@@ -918,7 +975,7 @@
             Transcript show:(TimeDuration milliseconds:millis).
         ].
     ].
-    cycles ~~ 0 ifTrue:[
+    cycles notNil ifTrue:[
         Transcript show:' ('; show:cycles; show:' cycles)'.
     ].
     Transcript cr.
@@ -936,6 +993,8 @@
      [10 factorial] benchmark:'11 factorial:'
      [100 factorial] benchmark:'100 factorial:'
     "
+
+    "Modified (comment): / 23-02-2017 / 21:06:29 / mawalch"
 ! !
 
 !Block methodsFor:'error handling'!
@@ -1532,17 +1591,16 @@
      i.e. change the priority for the execution of the receiver.
      Bad name: should be called evaluateWithPriority: or similar"
 
-    |oldPrio retVal activeProcess|
+    |oldPrio activeProcess|
 
     activeProcess := Processor activeProcess.
     oldPrio := Processor activePriority.
-    [
+    ^ [
 	activeProcess priority:priority.
-	retVal := self value.
+        self value.
     ] ensure:[
 	activeProcess priority:oldPrio
     ].
-    ^ retVal
 
     "
      [
@@ -1552,7 +1610,8 @@
      ] valueAt:3
     "
 
-    "Created: / 29.7.1998 / 19:19:48 / cg"
+    "Created: / 29-07-1998 / 19:19:48 / cg"
+    "Modified: / 23-06-2017 / 11:13:30 / stefan"
 !
 
 valueWithArguments:argArrayIn
@@ -1940,13 +1999,191 @@
     "
 ! !
 
+!Block methodsFor:'evaluation with timeout'!
+
+valueWithConfirmedTimeout:secondsOrTimeDuration confirmWith:confirmationBlock
+    "evaluate the receiver.
+     If not finished after secondsOrTimeDuration, call the confirmationBlock.
+     If it returns true, another time-interval is setup and we continue waiting.
+     If it returns a number (seconds) or a timeDuration, this time-interval is setup and we continue waiting.
+     If it returns false, nil is returned immediately.
+     
+     The receiver's code must be prepared
+     for premature returning (by adding ensure blocks, as required)"
+
+    |ok retVal interrupter|
+
+    ok := false.
+    interrupter := [ ok ifFalse:[ TimeoutError raiseRequest ] ].
+    [
+        Processor addTimedBlock:interrupter after:secondsOrTimeDuration.
+
+        TimeoutError handle:[:ex |
+            |answer nextWaitTime|
+            
+            answer := confirmationBlock valueWithOptionalArgument:ex.
+            answer == false ifTrue:[
+                ^ nil
+            ].
+            answer == true ifTrue:[
+                nextWaitTime := secondsOrTimeDuration
+            ] ifFalse:[
+                nextWaitTime := answer asTimeDuration
+            ].    
+            "/ proceed, setting up another timeout
+            Processor addTimedBlock:interrupter after:nextWaitTime.
+            ex proceed
+        ] do:[     
+            retVal := self value.
+            ok := true.
+        ].
+    ] ensure:[
+        Processor removeTimedBlock:interrupter.
+    ].
+    ^ retVal
+    
+    "
+     [
+        1 to:10 do:[:i | 
+            Transcript showCR:i.
+            1 seconds wait. 
+        ].
+        'finished'
+     ] valueWithConfirmedTimeout:(3 seconds) confirmWith:[
+        (Dialog confirm:'continue?')
+     ].
+    "
+    
+    "
+     [
+        1 to:10 do:[:i | 
+            Transcript showCR:i.
+            1 seconds wait. 
+        ].
+        'finished'
+     ] valueWithConfirmedTimeout:(3 seconds) confirmWith:[
+        (Dialog confirm:'wait another 5 seconds?') ifTrue:[
+            5
+        ] ifFalse:[
+            false
+        ].
+     ].
+    "
+
+    "Created: / 26-06-2019 / 11:46:02 / Claus Gittinger"
+!
+
+valueWithTimeout:aTimeDurationOrIntegerSeconds
+    "execute the receiver, but abort the evaluation after aTimeDuration if still running.
+     Return the receiver's value, or nil if aborted.
+
+     The receiver's code must be prepared
+     for premature returning (by adding ensure blocks, as required)"
+
+    |milliseconds|
+
+    milliseconds := aTimeDurationOrIntegerSeconds isTimeDuration
+                        ifTrue:[ aTimeDurationOrIntegerSeconds asMilliseconds ]
+                        ifFalse:[ (aTimeDurationOrIntegerSeconds * 1000) truncated].
+    ^ self valueWithWatchDog:[nil] afterMilliseconds:milliseconds
+
+    "
+     [
+        1 to:15 do:[:round |
+            Transcript showCR:round.
+            Delay waitForMilliseconds:20.
+        ].
+        true
+     ] valueWithTimeout:(TimeDuration seconds:1)
+    "
+
+    "
+     [
+        1 to:100 do:[:round |
+            Transcript showCR:round.
+            Delay waitForMilliseconds:20.
+        ].
+        true
+     ] valueWithTimeout:(TimeDuration seconds:1)
+    "
+
+    "Modified (comment): / 26-06-2019 / 11:53:25 / Claus Gittinger"
+!
+
+valueWithWatchDog:exceptionBlock afterMilliseconds:aTimeLimit
+    "a watchdog on a block's execution. If the block does not finish its
+     evaluation after aTimeLimit milliseconds, it is interrupted (aborted) and
+     exceptionBlock's value is returned. 
+
+     The receiver's code must be prepared
+     for premature returning (by adding ensure blocks, as required)"
+
+    |inError|
+
+    inError := false.
+
+    ^ TimeoutNotification handle:[:ex |
+        inError ifTrue:[
+            ex proceed
+        ].
+        exceptionBlock valueWithOptionalArgument:ex.
+    ] do:[
+        NoHandlerError handle:[:ex |
+            inError := true.
+            ex reject.
+        ] do:[
+            |showStopper me done|
+
+            done := false.
+            me := Processor activeProcess.
+            showStopper := [
+                    done ifFalse:[
+                        me interruptWith:[
+                            (done not and:[me isDebugged not]) ifTrue:[ 
+                                TimeoutNotification raiseRequest.
+                            ]
+                        ]
+                    ]
+                ].
+
+            [
+                |retVal|
+
+                Processor
+                    addTimedBlock:showStopper
+                    for:me
+                    afterMilliseconds:aTimeLimit.
+
+                retVal := self value.
+                done := true.
+                retVal
+            ] ensure:[
+                Processor removeTimedBlock:showStopper
+            ].
+        ]
+    ].
+
+    "
+     [
+        Delay waitForSeconds:5.
+        true
+     ] valueWithWatchDog:[false] afterMilliseconds:2000
+    "
+
+    "Modified: / 21-05-2010 / 12:19:57 / sr"
+    "Modified: / 19-03-2017 / 18:13:07 / cg"
+    "Modified: / 31-01-2018 / 08:34:51 / stefan"
+    "Modified: / 23-05-2018 / 12:47:00 / Maren"
+    "Modified (comment): / 26-06-2019 / 11:53:29 / Claus Gittinger"
+! !
+
 !Block methodsFor:'exception handling'!
 
 on:aSignalOrSignalSetOrException do:exceptionBlock
     "added for ANSI compatibility; evaluate the receiver,
      handling aSignalOrSignalSetOrException.
      If the signal is raised during evaluation,
-     the 2nd argument, exceptionBlock is evaluated (and its value returned"
+     the 2nd argument, exceptionBlock is evaluated (and its value returned)"
 
     <context: #return>
     <exception: #handle>
@@ -1972,7 +2209,8 @@
      ] on:Error do:[:ex| 2 ]   
     "
 
-    "Modified: / 26.7.1999 / 15:30:48 / stefan"
+    "Modified: / 26-07-1999 / 15:30:48 / stefan"
+    "Modified (comment): / 26-06-2019 / 11:55:55 / Claus Gittinger"
 !
 
 on:aSignalOrSignalSetOrException do:exceptionBlock ensure:ensureBlock
@@ -2000,23 +2238,39 @@
      e := 0.
      [
 	1 foo
-     ] on:MessageNotUnderstood
-     do:[:ex | self halt]
-     ensure:[ e := 1 ].
+     ] on:MessageNotUnderstood do:[:ex | 
+        self halt
+     ] ensure:[ 
+        e := 1 
+     ].
      self assert:(e == 1).
     "
 
     "
+     [
+        1 foo
+     ] on:MessageNotUnderstood do:[:ex | 
+        ^ self
+     ] ensure:[ 
+        Transcript showCR:'ensure ensured'
+     ].
+    "
+
+    "
      |e|
 
      e := 0.
      [
 	1 negated
-     ] on:MessageNotUnderstood
-     do:[:ex | self halt]
-     ensure:[ e := 1 ].
+     ] on:MessageNotUnderstood do:[:ex | 
+        self halt
+     ] ensure:[ 
+        e := 1 
+     ].
      self assert:(e == 1).
     "
+
+    "Modified (comment): / 30-05-2018 / 21:20:14 / Claus Gittinger"
 !
 
 on:aSignalOrSignalSetOrException do:exceptionBlock ifCurtailed:curtailBlock
@@ -2076,6 +2330,20 @@
      ifCurtailed:[ e := 1 ].
      self assert:(e == 0).
     "
+
+
+    "
+     |e|
+
+     e := 0.
+     [
+        1 foo
+     ] on:MessageNotUnderstood do:[:ex | 2 bla]
+       ifCurtailed:[ e := 1 ].
+     self assert:(e == 0).
+    "
+
+    "Modified (comment): / 23-03-2017 / 19:10:31 / stefan"
 !
 
 on:anExceptionHandler do:exceptionBlock on:anExceptionHandler2 do:anExceptionBlock2
@@ -2117,96 +2385,6 @@
 
     "Created: / 26.7.1999 / 11:23:45 / stefan"
     "Modified: / 26.7.1999 / 11:24:06 / stefan"
-!
-
-valueWithTimeout:aTimeDurationOrIntegerSeconds
-    "execute the receiver, but abort the evaluation after aTimeDuration if still running.
-     Return the receiver's value, or nil if aborted."
-
-    |milliseconds|
-
-    milliseconds := aTimeDurationOrIntegerSeconds isTimeDuration
-                        ifTrue:[ aTimeDurationOrIntegerSeconds asMilliseconds ]
-                        ifFalse:[ (aTimeDurationOrIntegerSeconds * 1000) truncated].
-    ^ self valueWithWatchDog:[^ nil] afterMilliseconds:milliseconds
-
-    "
-     [
-        1 to:15 do:[:round |
-            Transcript showCR:round.
-            Delay waitForMilliseconds:20.
-        ].
-        true
-     ] valueWithTimeout:(TimeDuration seconds:1)
-    "
-
-    "
-     [
-        1 to:100 do:[:round |
-            Transcript showCR:round.
-            Delay waitForMilliseconds:20.
-        ].
-        true
-     ] valueWithTimeout:(TimeDuration seconds:1)
-    "
-!
-
-valueWithWatchDog:exceptionBlock afterMilliseconds:aTimeLimit
-    "a watchdog on a block's execution. If the block does not finish its
-     evaluation after aTimeLimit milliseconds, it is interrupted (aborted) and
-     exceptionBlock's value is returned. The receiver's code must be prepared
-     for premature returning (by adding ensure blocks, as required)"
-
-    |showStopper me retVal done inError|
-
-    done := false.
-    me := Processor activeProcess.
-
-    showStopper :=
-	[
-	    done ifFalse:[
-		me interruptWith:[
-		    (Processor activeProcess state ~~ #debug) ifTrue:[
-			done ifFalse:[ TimeoutNotification raiseRequest ]
-		    ]
-		]
-	    ]
-	].
-
-    TimeoutNotification handle:[:ex |
-	inError ifTrue:[
-	    ex proceed
-	].
-	retVal := exceptionBlock value.
-    ] do:[
-	NoHandlerError handle:[:ex |
-	    inError := true.
-	    ex reject.
-	] do:[
-	    [
-		Processor
-		    addTimedBlock:showStopper
-		    for:me
-		    afterMilliseconds:aTimeLimit.
-
-		retVal := self value.
-		done := true.
-	    ] ensure:[
-		Processor removeTimedBlock:showStopper
-	    ].
-	]
-    ].
-    ^ retVal
-
-    "
-     [
-	Delay waitForSeconds:5.
-	true
-     ] valueWithWatchDog:[false] afterMilliseconds:2000
-    "
-
-    "Modified: / 21-05-2010 / 12:19:57 / sr"
-    "Modified: / 18-01-2011 / 19:24:13 / cg"
 ! !
 
 !Block methodsFor:'exception handling private'!
@@ -2220,20 +2398,7 @@
 	exceptionCreator := anException creator.
 	exceptionHandlerInContext := aContext argAt:1.
 	exceptionHandlerInContext isExceptionHandler ifFalse:[
-	    exceptionHandlerInContext isNil ifTrue:[
-		'Block [warning]: nil ExceptionHandler in on:do:on:do:-context' errorPrintCR.
-	    ] ifFalse:[
-		(exceptionHandlerInContext isBehavior
-		and:[exceptionHandlerInContext isLoaded not]) ifTrue:[
-		    "If the exception class is still autoloaded,
-		     it does not accept our exception. Raising the exception would load the class"
-		    ^ nil
-		] ifFalse:[
-		    'Block [warning]: non-ExceptionHandler in on:do:on:do:-context' errorPrintCR.
-		]
-	    ].
-	    aContext fullPrintString errorPrintCR.
-	    self breakPoint:#cg.
+            GenericException printBadExceptionHandler:exceptionHandlerInContext in:aContext.
 	    ^ nil.
 	].
 	(exceptionHandlerInContext accepts:exceptionCreator) ifTrue:[
@@ -2242,20 +2407,7 @@
 
 	exceptionHandlerInContext := aContext argAt:3.
 	exceptionHandlerInContext isExceptionHandler ifFalse:[
-	    exceptionHandlerInContext isNil ifTrue:[
-		'Block [warning]: nil ExceptionHandler in on:do:on:do:-context' errorPrintCR.
-	    ] ifFalse:[
-		(exceptionHandlerInContext isBehavior
-		and:[exceptionHandlerInContext isLoaded not]) ifTrue:[
-		    "If the exception class is still autoloaded,
-		     it does not accept our exception. Raising the exception would load the class"
-		    ^ nil
-		] ifFalse:[
-		    'Block [warning]: non-ExceptionHandler in on:do:on:do:-context' errorPrintCR.
-		]
-	    ].
-	    aContext fullPrintString errorPrintCR.
-	    self breakPoint:#cg.
+            GenericException printBadExceptionHandler:exceptionHandlerInContext in:aContext.
 	    ^ nil.
 	].
 	(exceptionHandlerInContext accepts:exceptionCreator) ifTrue:[
@@ -2268,89 +2420,59 @@
     ^ aContext argAt:1.
 !
 
-handlerForSignal:exceptionCreator context:theContext originator:originator
+handlerForSignal:exceptionCreator context:aContext originator:originator
     "answer the handler block for the exceptionCreator from originator.
      The handler block is retrieved from aContext.
      Answer nil if the exceptionCreator is not handled."
 
     |selector exceptionHandlerInContext|
 
-    selector := theContext selector.
+    selector := aContext selector.
 
     (selector == #on:do:
      or:[ selector == #on:do:ensure: 
      or:[ selector == #on:do:ifCurtailed: ]]
      ) ifTrue:[
-        exceptionHandlerInContext := theContext argAt:1.
+        exceptionHandlerInContext := aContext argAt:1.
         exceptionHandlerInContext isExceptionHandler ifFalse:[
-            exceptionHandlerInContext isNil ifTrue:[
-                'Block [warning]: nil ExceptionHandler in on:do:on:do:-context' errorPrintCR.
-            ] ifFalse:[(exceptionHandlerInContext isBehavior
-                        and:[exceptionHandlerInContext isLoaded not]) ifTrue:[
-                "If the exception class is still autoloaded,
-                 it does not accept our exception. Raising the exception would load the class"
-                ^ nil
-            ] ifFalse:[
-                'Block [warning]: non-ExceptionHandler in on:do:-context' errorPrintCR.
-            ]].
-            theContext fullPrint.
+            GenericException printBadExceptionHandler:exceptionHandlerInContext in:aContext.
             ^ nil.
         ].
         (exceptionHandlerInContext == exceptionCreator
          or:[exceptionHandlerInContext accepts:exceptionCreator]) ifTrue:[
             selector == #on:do:ifCurtailed: ifTrue:[
-                theContext unmarkForUnwind.     "if there is a handler, no unwind block has to be performed"
+                aContext unmarkForUnwind.     "if there is a handler, no unwind block has to be performed"
             ].
-            ^ (theContext argAt:2) ? [nil].
+            ^ (aContext argAt:2) ? [nil].
         ].
         ^ nil
     ].
 
     selector == #on:do:on:do: ifTrue:[
-        exceptionHandlerInContext := theContext argAt:1.
+        exceptionHandlerInContext := aContext argAt:1.
         exceptionHandlerInContext isExceptionHandler ifFalse:[
-            exceptionHandlerInContext isNil ifTrue:[
-                'Block [warning]: nil ExceptionHandler in on:do:on:do:-context' errorPrintCR.
-            ] ifFalse:[(exceptionHandlerInContext isBehavior
-                        and:[exceptionHandlerInContext isLoaded not]) ifTrue:[
-                "If the exception class is still autoloaded,
-                 it does not accept our exception. Raising the exception would load the class"
-                ^ nil
-            ] ifFalse:[
-                'Block [warning]: non-ExceptionHandler in on:do:on:do:-context' errorPrintCR.
-            ]].
-            theContext fullPrint.
+            GenericException printBadExceptionHandler:exceptionHandlerInContext in:aContext.
             ^ nil.
         ].
         (exceptionHandlerInContext == exceptionCreator
          or:[exceptionHandlerInContext accepts:exceptionCreator]) ifTrue:[
-            ^ (theContext argAt:2) ? [nil].
+            ^ (aContext argAt:2) ? [nil].
         ].
 
-        exceptionHandlerInContext := theContext argAt:3.
+        exceptionHandlerInContext := aContext argAt:3.
         exceptionHandlerInContext isExceptionHandler ifFalse:[
-            exceptionHandlerInContext isNil ifTrue:[
-                'Block [warning]: nil ExceptionHandler in on:do:on:do:-context' errorPrintCR.
-            ] ifFalse:[(exceptionHandlerInContext isBehavior
-                        and:[exceptionHandlerInContext isLoaded not]) ifTrue:[
-                "If the exception class is still autoloaded,
-                 it does not accept our exception. Raising the exception would load the class"
-                ^ nil
-            ] ifFalse:[
-                'Block [warning]: non-ExceptionHandler in on:do:on:do:-context' errorPrintCR.
-            ]].
-            theContext fullPrint.
+            GenericException printBadExceptionHandler:exceptionHandlerInContext in:aContext.
             ^ nil.
         ].
         (exceptionHandlerInContext == exceptionCreator
          or:[exceptionHandlerInContext accepts:exceptionCreator]) ifTrue:[
-            ^ (theContext argAt:4) ? [nil].
+            ^ (aContext argAt:4) ? [nil].
         ].
         ^ nil
     ].
 
     selector == #valueWithExceptionHandler: ifTrue:[
-        ^ (theContext argAt:1) handlerForSignal:exceptionCreator.
+        ^ (aContext argAt:1) handlerForSignal:exceptionCreator.
     ].
 
     "/ mhmh - should not arrive here
@@ -2837,11 +2959,13 @@
     sourcePos isString ifTrue:[    "/ misuses the sourcePosition slot
 	^ sourcePos
     ].
-    m := self method.
+    m := self homeMethod.
     m notNil ifTrue:[
 	^ m source
     ].
     ^ nil
+
+    "Modified: / 31-03-2017 / 17:26:52 / stefan"
 !
 
 source:aString
@@ -2887,7 +3011,10 @@
 	^ self value
     ].
 
+    "/ was not blocked
     ^ self ensure:[OperatingSystem unblockInterrupts].
+
+    "Modified (comment): / 24-07-2017 / 18:03:04 / cg"
 !
 
 valueUnpreemptively
@@ -2947,36 +3074,34 @@
      passing the elements in argArray as arguments to the receiver block."
 
     ^ [self valueWithArguments:argArray] newProcess
-!
-
-promise
-    "create a promise on the receiver. The promise will evaluate the
-     receiver and promise to return the value with the #value message.
-     The evaluation will be performed as a separate process.
-     Asking the promise for its value will either block the asking process
-     (if the evaluation has not yet been finished) or return the value
-     immediately."
-
-    ^ Promise value:self
+! !
+
+!Block methodsFor:'splitting & joining'!
+
+split: aSequenceableCollection indicesDo: aBlock
+    "let me split aSequenceableCollection and evaluate aBlock for each fragment's
+     start- and end-position"
+
+    | position |
+
+    position := 1.
+    aSequenceableCollection withIndexDo:[:element :idx |
+        (self value: element) ifTrue:[
+            aBlock value: position value: idx - 1.
+            position := idx + 1 
+        ]
+    ].
+    aBlock value: position value: aSequenceableCollection size
 
     "
-     |p|
-
-     p := [1000 factorial] promise.
-     'do something else ...'.
-     p value
+        [ :char| char isSeparator ] split: 'aa bb cc dd'
+
+        [ :char| char isSeparator ] split: 'aa bb cc dd' do:[:fragment | Transcript showCR:fragment ]
+
+        [ :char| char isSeparator ] split: 'aa bb cc dd' indicesDo:[:start :end | Transcript show:start; show:' to '; showCR:end ]
     "
-!
-
-promiseAt:prio
-    "create a promise on the receiver. The promise will evaluate the
-     receiver and promise to return the value with the #value message.
-     The evaluation will be performed as a separate process running at prio.
-     Asking the promise for its value will either block the asking process
-     (if the evaluation has not yet been finished) or return the value
-     immediately."
-
-    ^ Promise value:self priority:prio
+
+    "Created: / 13-07-2017 / 18:32:09 / cg"
 ! !
 
 !Block methodsFor:'testing'!
@@ -2987,6 +3112,14 @@
     ^ true
 !
 
+isBlockWithArgumentCount:count
+    "return true, if this is a block with count args"
+
+    ^ nargs == count
+
+    "Created: / 18-03-2017 / 18:07:03 / stefan"
+!
+
 isCheapBlock
     ^ false
 !