Author: Jan Nijtmans <jan.nijtmans@gmail.com>
State: Draft
Type: Project
Tcl-Version: 9.1
Vote: Pending
Created: 05-Feb-2026
Keywords: bool
Tcl-Branch: tip-748
Abstract
This TIP proposes to add change all public functions which return a int which
is actually a bool, to change the return type to bool.
Rationale
Using a bool has the advantage that the compiler can optimize the code more,
because there are only 2 possible values. For int's this assumtion cannot be made.
Specification
For compilers needing it, #include <stdbool.h> will be included in tcl.h.
In conforming C23 compilers, bool is a new keyword which can be used without any
extra header file. In time, the need for this extra header file will disappear.
The following funtions are changed, returning a bool:
- Tcl_IsShared()
- Tcl_AsyncReady()
- Tcl_IsSafe()
- Tcl_UniCharIsAlnum()
- Tcl_UniCharIsAlpha()
- Tcl_UniCharIsDigit()
- Tcl_UniCharIsLower()
- Tcl_UniCharIsSpace()
- Tcl_UniCharIsUpper()
- Tcl_UniCharIsWordChar()
- Tcl_UniCharIsControl()
- Tcl_UniCharIsGraph()
- Tcl_UniCharIsPrint()
- Tcl_UniCharIsPunct()
- Tcl_IsChannelShared()
- Tcl_IsChannelRegistered()
- Tcl_IsChannelExisting()
- Tcl_IsStandardChannel()
- Tcl_IsEnsemble()
- Tcl_AsyncMarkFromSignal()
- Tcl_IsEmpty()
For Tk, the list is:
- Tk_CharBbox()
- Tk_SetWindowVisual()
- Tk_StrictMotif()
- Tk_CollapseMotionEvents()
- Tk_AlwaysShowSelection()
- Tk_MacOSXIsAppInFront()
There is a catch. Functions returning a bool, use less bits in the register where
the value is returned (like the EAX register on x68). So, bits 0-7 will have the
expected value, but bits 8-31 of this register might just have some random value
left over from previous code. Older extensions compiled with older (Tcl 9.0) header
files which still used int, might interpret those random bits as non-zero, or true.
The solution for this is fill the stub table with wrapper functions, which extend
the EAX register filling bits 8-31 with all zero's. This way, callers expecting an
int will behave the same way as callers expecting a bool.
Here is an example wrapper function (in x68_64 assembler)
Tcl_IsEqual_stub_wrapper(Tcl_Obj *):
call Tcl_IsEqual(Tcl_Obj *)
movzx eax, al
ret
The movzx (move with zero extend) extends the 8-bit result from the Tcl_IsEqual() call to 32 bits.
On other processors, the instruction used might be different (e.g "and eax, 255" on x86, "and w0, w0, 255" on ARM64).
On WebAssembly, bool's are always returned as 32-bit integers, so no wrapper functions are needed. In C
it is not possible to return a boolean in a processor flag (like the carry flag). Some signal-processors
might do that (even though it's not according to the C standard), then the same approach as WebAssembly can be used.
The other way around, extensions compiled with Tcl 9.1 headers but running on Tcl 9.0,
is no problem. This way, there is both forward and backward binary compatibility
between Tcl 9.0 and 9.1. Extensions compiled with Tcl 9.1 headers can make use of the
bool optimizations, while extensions compiled with Tcl 9.0 headers cannot, but that's
the only difference.
Reference Implementation
See the tip-748 branch.
Copyright
This document has been placed in the public domain.