[REBOL] Words, Bindings and Contexts. (7)
From: lmecir:geocities at: 25-Jul-2000 22:37
I see, that the fact, that my series didn't explain the behaviour
of functions WRT Recursion and Binding is a flaw. Here is the
continuation (a model of the behaviour):
; Model of Rebol function:
; ****************************
sim-function!: make object! [
; every function has got a Context attribute
context: none
; every function has got a Spec attribute
spec: none
; every function has got a Body attribute
body: none
; every function has got a provision for Recursion
recursion-level: 0
stack: none
]
; Model of Func function:
; ***************************
sim-func: func [
{create a Sim-function!}
spec [block!]
body [block!]
/local context-init spec-too body-too
] [
; first of all, the function context should be created
context-init: make block! 1 + length? spec
foreach word spec [
append context-init to set-word! word
]
append context-init none
spec-too: spec
body-too: body
make sim-function! [
; create context
context: make object! context-init
; a simplification here
spec: bind/copy spec-too in context 'self
; this is the secret of "Context Hierachy"
body: bind/copy body-too in context 'self
; Create a stack for storing values during recursive calls
stack: copy []
]
]
; Model of the function body execution:
; ******************************************
do-body: func [body] [do body]
; Model of the return from function:
; **************************************
sim-return: func [
sim-f
value [any-type!]
] [
; restore the former values from stack, if needed
if (sim-f/recursion-level: sim-f/recursion-level - 1) > 0 [
set/any sim-f/spec first sim-f/stack
; finish the stack-pop
sim-f/stack: remove sim-f/stack
]
; return the value
return get/any 'value
]
; Model of function Evaluation:
; *********************************
sim-evaluate: func [
{evaluate a sim-function contained in a block with its
arguments}
block [block!]
/local sim-f actual-values
] [
; evaluate the arguments
block: reduce block
; the executed sim-function is first
sim-f: first block
; detect recursion
if (sim-f/recursion-level: sim-f/recursion-level + 1) > 1 [
; get the actual values of local words
actual-values: copy []
foreach word sim-f/spec [
append/only actual-values get/any word
]
; push the actual values to stack
sim-f/stack: head insert/only sim-f/stack actual-values
]
; give local words the supplied values
set/any sim-f/spec next block
; execute the function body and return the result
return sim-return sim-f do-body sim-f/body
]
; Some tests:
; **************
blk: copy []
probeblk: func [] [
prin mold blk
prin ": "
print mold reduce blk
]
recfun: sim-func [x] [
append blk 'x
either x <= 1 [
probeblk
] [
sim-evaluate [recfun x - 1]
]
]
sim-evaluate [recfun 3]
probeblk