On 11/08/2016 08:05, Charlie Bursell wrote:
> What am I not understanding here?
There is a space after the backslash (which appears to be a cut-n-paste
error somehow; I've just fixed the wiki page). You can see that things
have gone wrong by disassembling the [makeIota] command:
> % tcl::unsupported::disassemble proc makeIota
> ByteCode 0x0x1008bfc10, refCt 1, epoch 17, interp 0x0x100829a10
(epoch 17)
> Source " \n set cmd [UNIQUE_NAME] \n coroutine $cmd apply"...
> Cmds 5, src 137, inst 42, litObjs 6, aux 0, stkDepth 5, code/src 0.00
> Proc 0x0x1008d2a10, refCt 1, args 2, compiled locals 3
> slot 0, scalar, arg, "start"
> slot 1, scalar, arg, "end"
> slot 2, scalar, "cmd"
> Commands 5:
> 1: pc 0-6, src 6-27 2: pc 0-3, src 15-25
> 3: pc 7-19, src 33-88 4: pc 20-28, src 102-118
> 5: pc 29-40, src 124-135
> Command 1: "set cmd [UNIQUE_NAME] "...
> Command 2: "UNIQUE_NAME"...
> (0) push1 0 # "UNIQUE_NAME"
> (2) invokeStk1 1
> (4) storeScalar1 %v2 # var "cmd"
> (6) pop
> Command 3: "coroutine $cmd apply {args {yield;tailcall {*}$args}} \"...
> (7) push1 1 # "coroutine"
> (9) loadScalar1 %v2 # var "cmd"
> (11) push1 2 # "apply"
> (13) push1 3 # "args {yield;tailcall {*}$args}"
> (15) push1 4 # " "
> (17) invokeStk1 5
> (19) pop
> Command 4: "iota $start $end "...
> (20) push1 5 # "iota"
> (22) loadScalar1 %v0 # var "start"
> (24) loadScalar1 %v1 # var "end"
> (26) invokeStk1 3
> (28) pop
> Command 5: "return $cmd "...
> (29) startCommand +12 1 # next cmd at pc 41, 1 cmds start here
> (38) loadScalar1 %v2 # var "cmd"
> (40) done
> (41) done
If you look at Command 3's implementation, you see a pushing of a space
as an argument before the invokeStk, followed by Command 4 which is a
direct call of [iota]. That's not right at all! Fixing the trivial
whitespace issue will instead give this disassembly:
> % tcl::unsupported::disassemble proc makeIota
> ByteCode 0x0x1008bfc10, refCt 1, epoch 17, interp 0x0x100829a10
(epoch 17)
> Source " \n set cmd [UNIQUE_NAME] \n coroutine $cmd apply"...
> Cmds 4, src 123, inst 37, litObjs 5, aux 0, stkDepth 7, code/src 0.00
> Proc 0x0x102048490, refCt 1, args 2, compiled locals 3
> slot 0, scalar, arg, "start"
> slot 1, scalar, arg, "end"
> slot 2, scalar, "cmd"
> Commands 4:
> 1: pc 0-6, src 6-27 2: pc 0-3, src 15-25
> 3: pc 7-23, src 33-104 4: pc 24-35, src 110-121
> Command 1: "set cmd [UNIQUE_NAME] "...
> Command 2: "UNIQUE_NAME"...
> (0) push1 0 # "UNIQUE_NAME"
> (2) invokeStk1 1
> (4) storeScalar1 %v2 # var "cmd"
> (6) pop
> Command 3: "coroutine $cmd apply {args {yield;tailcall {*}$args}} "...
> (7) push1 1 # "coroutine"
> (9) loadScalar1 %v2 # var "cmd"
> (11) push1 2 # "apply"
> (13) push1 3 # "args {yield;tailcall {*}$args}"
> (15) push1 4 # "iota"
> (17) loadScalar1 %v0 # var "start"
> (19) loadScalar1 %v1 # var "end"
> (21) invokeStk1 7
> (23) pop
> Command 4: "return $cmd "...
> (24) startCommand +12 1 # next cmd at pc 36, 1 cmds start here
> (33) loadScalar1 %v2 # var "cmd"
> (35) done
> (36) done
See how the "iota" and the contents of the variables are passed into the
call to [coroutine]? That's looking like what we expect, and works
correctly too.
Donal.
--
Donal Fellows — Tcl user, Tcl maintainer, TIP editor.