#class(#pointer) Context(Apex) { #dcl sender ip sp ntmprs. #method sender { ^self.sender } #method isExceptionHandlerContext { ^false } } #class(#pointer) MethodContext(Context) { #dcl method receiver home origin. #method pc { ^self.ip } #method pc: anInteger { self.ip := anInteger. "self.sp := self.sp - 1." "whould this always work??? " } #method sp { ^self.sp. } #method sp: anInteger { self.sp := anInteger. } #method pc: aPC sp: aSP { self.ip := aPC. self.sp := aSP. ##sp := sp - 1. } #method method { ^self.method } #method isExceptionHandlerContext { ## 10 - STIX_METHOD_PREAMBLE_EXCEPTION in VM. ^self.method preambleCode == 10. } #method findExceptionHandlerBlock: anExceptionClass { ## for this to work, self must be an exception handler context. ## For a single on:do: call, ## self class specNumInstVars must return 8. ## basicAt: 8 must be the on: argument. ## basicAt: 9 must be the do: argument (self isExceptionHandlerContext) ifTrue: [ | bound exc | ## NOTE: if on:do: has a temporary varible, bound must be adjusted to reflect it. bound := self basicSize - 1. 8 to: bound by: 2 do: [ :i | exc := self basicAt: i. ((anExceptionClass == exc) or: [anExceptionClass inheritsFrom: exc]) ifTrue: [^self basicAt: (i + 1)]. ] ]. ^nil. } } #class(#pointer) BlockContext(Context) { #dcl nargs source home origin. #method fork { "crate a new process in the runnable state" ^self newProcess resume. } #method newProcess { "create a new process in the suspended state" self primitiveFailed. } #method newProcessWith: anArray { "create a new process in the suspended state passing the elements of anArray as block arguments" self primitiveFailed. } #method value { self primitiveFailed. } #method value: a { self primitiveFailed. } #method value: a value: b { self primitiveFailed. } #method value: a value: b value: c { self primitiveFailed. } #method ifTrue: aBlock { ^(self value) ifTrue: aBlock. } #method ifFalse: aBlock { ^(self value) ifFalse: aBlock. } #method ifTrue: trueBlock ifFalse: falseBlock { ^(self value) ifTrue: trueBlock ifFalse: falseBlock } #method whileTrue: aBlock { ## http://stackoverflow.com/questions/2500483/is-there-a-way-in-a-message-only-language-to-define-a-whiletrue-message-without ## ---------------------------------------------------------------------------- ## ^(self value) ifTrue: [aBlock value. self whileTrue: aBlock]. ## ---------------------------------------------------------------------------- ## less block context before whileTrue: is recursively sent. ## whileTrue: is sent in a method context. (self value) ifFalse: [^nil]. aBlock value. self whileTrue: aBlock. ## ---------------------------------------------------------------------------- ## ---------------------------------------------------------------------------- " | pc sp xsp | sp := thisContext sp. sp := sp - 1. ## decrement sp by 1 becuase thisContext pushed above affects the sp method pc := thisContext pc. self value ifFalse: [ ^nil "^self" ]. aBlock value. ##thisContext pc: pc - 3 sp: sp. ##thisContext pc: pc + 2 sp: sp. thisContext pc: pc + 1 sp: sp. ## this +2 or - 3 above is dependent on the byte code instruction size used for 'store' ## +2 to skip STORE_INTO_TEMP(pc) and POP_STACKTOP. ## TODO: make it independent of the byte code size " ## ---------------------------------------------------------------------------- ## #