Reputation: 1
When you start a tcl script, what is the background process that happens. ( similar to c compilation )?
When you start the expect, how the script process works?
Upvotes: 0
Views: 477
Reputation: 7247
Assuming you already have a running Tcl interpreter and just source
your script to run it (which avoids describing the whole interpreter startup sequence and initialization), the following things happen in any recent (8.x) Tcl interpreter.
This basically invokes some C-Code like Tcl_EvalFile()
which loads the script into memory, and hands of the work of actually doing the execution to the internal TclEvalEx()
, which is a private version of Tcl_EvalEx()
, as documented here (https://www.tcl.tk/man/tcl/TclLib/Eval.htm).
This interprets the toplevel script without bytecode compilation, e.g. the script is parsed, once a command is found, it is executed directly. This is quite slow and the way the older Tcl 7.x operated all the time.
But if a command is executed, it is checked if the command can be byte-compiled into a more efficient form. This is the case for commands defined via proc
so if a command gets executed the first time, the Tcl_EvalObjEx()
calls TclCompileObj()
internally to get a bytecode representation of the command, which is cached inside the Tcl_Obj
of the parsed command.
If the command cannot be compiled, it is executed directly, e.g. one of the functions in generic/tclCmd*.c
is called, for example to handle the command concat
the command would be Tcl_ConcatObjCmd()
in generic/tclCmdAH.c
. This function may also come from some C extension loaded into the interpreter and is treated exactly in the same way. The available commands are registered internally in some hash table, thats what Tcl_CreateObjCmd()
does.
But if the command can be compiled, something different happens. In that case, the command is turned into a bytecode representation. For example for a trivial procedure like this: proc c {a b} {concat $a $b}
this is turned into four bytecodes. You can actually inspect the generated bytecode via the ::tcl::unsupported::disassemble
command, have a look at this Tkcon session with a Tcl 8.6.3:
() 69 % proc c {a b} {concat $a $b}
() 70 % ::tcl::unsupported::disassemble proc c
ByteCode 0x00000000045A2660, refCt 1, epoch 16, interp 0x0000000002E26120 (epoch 16)
Source "concat $a $b"
Cmds 1, src 12, inst 10, litObjs 0, aux 0, stkDepth 2, code/src 0.00
Proc 0x0000000002EB32A0, refCt 1, args 2, compiled locals 2
slot 0, scalar, arg, "a"
slot 1, scalar, arg, "b"
Commands 1:
1: pc 0-8, src 0-11
Command 1: "concat $a $b"
(0) loadScalar1 %v0 # var "a"
(2) loadScalar1 %v1 # var "b"
(4) concatStk 2
(9) done
This bytecode (the four lines at the bottom) is executed by a virtual machine inside the Tcl interpreter. It is a stack based VM currently. You can find its implementation inside the generic/tclExecute.c
file.
Not all commands can be bytecoded yet, if a command has no matching bytecode, a call to the plain function is generated, e.g. one of the Tcl_*ObjCmd
things mentioned for direct execution.
Bytecodes are much faster for most cases (nearly every time a command is reused). That is one reason for the advices to put all your code inside procedures (they get byte-compiled that way), and to brace your expressions.
Hope this illustrates the process a bit. I left out a few more complex details like compile epoches and the problems of co-routines, non-recursive engine etc.
Expect is identical to a normal Tcl for this, it just adds a few extra commands via Tcl_CreateObjCmd()
.
Upvotes: 1