TIP 484: Merge 'int' and 'wideInt' Obj-type to a single 'int'

Login
Bounty program for improvements to Tcl and certain Tcl packages.
Author:         Jan Nijtmans <jan.nijtmans@gmail.com>
State:          Draft
Type:           Project
Vote:           Pending
Created:        06-Nov-2017
Post-History:
Keywords:       Tcl
Tcl-Version:    8.7

Abstract

The 'wideInt' type was invented for Tcl because the 'int' type (which was actually 'long') was not sufficient to store numbers larger than [+-]2**31. This TIP proposes to merge the 'int' and the 'wideInt' Obj-types such that 'int' does all internal calculations using Tcl_WideInt in stead of long.

Rationale

For linux64, the 'wideInt' type doesn't give any advantage, it is #ifdef'd out in the code. For Windows 64, since 'long' is the same as 'int', it would be an advantage to use __int64 for all internal number processing. Since __int64 calculations are just as efficient as int/long calculations on most (64-bit and 32-bit) processors, it would save all kinds of range checks in the Tcl code. That's the main gain of this TIP.

Finally, for 32-bit systems, getting rid of 'wideInt' could give a small disadvantage on systems which split 64-bit calculations in terms of 32-bit calculations. There 32-bit calculations could become slightly slower.

Since the gain for 64-bit platforms (mainly Win64) is expected to be more than the possible loss on some 32-bit system, I still propose to follow this road.

Another advantage of this change is maintainability of number handling. Currently the C code contains a lot of #ifdef's which check whether sizeof(long) is the same a sizeof(wideint). All those checks can be removed, so the number handling becomes identical on all platforms supported by Tcl.

Proposal

Merge 'int' and 'wideInt' Obj-type to a single 'int'. Make the following changes:

  • Change the signature of the internal function TclFormatInt to int TclFormatInt(char *buffer, Tcl_WideInt n) so it can handle the full range of wide integers.

  • Modify the internal TclGetNumberFromObj function to always return TCL_NUMBER_WIDE in stead of TCL_NUMBER_LONG. This indicates that the internalRep.wideValue contains the actual internal representation of numbers. TCL_NUMBER_LONG is not used anymore, except in the bytecode implementation for string is integer and string is wideinteger. On script level this change is not detectable.

  • Modify the 'int' type to store its internal representation in internalRep.wideValue in stead of internalRep.longValue. This means that the 'int' type gains the full functionality of 'wideInt' on all platforms. This makes all 'wideInt' special code redundant, so it can full be removed from the Tcl code base.

Compatibility

On systems where sizeof(int) == sizeof(long), there are no compatibility issues, since the 'wideInt' type code is #ifdef'ed out anyway. On other systems there are only two possibilities:

  • The function call Tcl_GetObjType("wideInt") will return NULL, where it returned non-NULL before.

  • External code which accesses internalRep.longValue directly (after checking that the objType is 'int') will start to mis-behave as well.

However, both of these examples are nonportable, since no external code may make assumptions of implementation details for 'int'.

No test-cases are modified in the 'no-wideint' branch, all current test-cases continue to pass. This shows that separating the 'int' and the 'wideInt' implementation is nowhere required to let Tcl number handling function the way it functions now. At the script level, the change is invisible.

Reference Implementation

An implementation of this TIP can be found in the no-wideint branch.

The code is licensed under the same license as Tcl.

Copyright

This document has been placed in the public domain.

History