Ticket UUID: | 420507 | |||
Title: | Inconsistent behaviour of [unknown] | |||
Type: | Bug | Version: | None | |
Submitter: | msofer | Created on: | 2001-05-01 18:03:56 | |
Subsystem: | 45. Parsing and Eval | Assigned To: | msofer | |
Priority: | 7 High | Severity: | ||
Status: | Closed | Last Modified: | 2004-09-22 09:39:51 | |
Resolution: | Fixed | Closed By: | msofer | |
Closed on: | 2001-05-07 01:02:20 | |||
Description: |
There is an inconsistency in the handling of [unknown]: the bytecode engine always calls the global [unknown], the direct eval engine calls [unknown] in the local namespace. The following illustrates the bug: % info patchlevel 8.4a2 % namespace eval mig {set l aaa} aaa % proc unknown args {puts global} % proc mig::unknown args {puts local} % namespace eval mig {$l} global % namespace eval mig {eval $l} local It is quite straightforward to patch the source to obtain a consistent behaviour. The patch will be either in generic/tclExecute.c (to get the bytecode compiler to call the namespace [unknown]), or else in generic/tclParse.c. I do not know which of the two behaviours is the correct one! The man page for 'unknown' does not resolve the issue. OTOH, the behaviour was consistent in 8.0.5 (always call [::unknown]): % info patchlevel 8.0.5 % namespace eval mig {set l aaa} aaa % proc unknown args {puts global} % proc mig::unknown args {puts local} % namespace eval mig {$l} global % namespace eval mig {eval $l} global I have not tested other versions. | |||
User Comments: |
coldstore added on 2004-09-22 09:39:51:
Logged In: YES user_id=19214 For what it's worth, it seems to me that this inconsistency was resolved in the least useful way. Overriding unknown in a namespace would be a useful facility, qv TIP 181 msofer added on 2001-05-04 04:18:24: Logged In: YES user_id=148712 Patch registered as #421166 and committed. hobbs added on 2001-05-04 03:29:10: Logged In: YES user_id=72656 The patch from Miguel restores the unknown call to always ensure ::unknown, which seems correct. Unless you want to be able to override unknown in a namespace, but that isn't defined anywhere, nor does it work currently (as the examples below show). I recommend applying the patch from Miguel as is. That also makes things consistent with the actual unknown docs (which make no allowance for any other unknown but the global one). msofer added on 2001-05-04 00:47:04: Logged In: YES user_id=148712 Clarification: * the bug is exposed since 8.1, exposed by proc unknown args {puts global} namespace eval mig { proc unknown args {puts local} } namespace eval mig aaa ; # global namespace eval mig aaa bbb; # local namespace eval mig {aaa bbb}; # global * the modifications that created the "pure lists" optimisation for eval (8.3) led to a further exposure of the bug. The original script only shows this second exposure. dgp added on 2001-05-03 21:46:15: Logged In: YES user_id=80530 I assure you, Miguel, the behavior change takes place between 8.2.3 and 8.3b1. Regardez: $ cat un.tcl puts [info patchlevel] namespace eval mig {set l aaa} proc unknown args {puts global} proc mig::unknown args {puts local} namespace eval mig {$l} namespace eval mig {eval $l} namespace eval mig [list eval aaa] namespace eval mig [list aaa] namespace eval mig eval aaa namespace eval mig aaa $ /usr/local/src/tcl8.2.3/unix/tclsh un.tcl 8.2.3 global global global global global global $ /usr/local/src/tcl8.3b1/unix/tclsh un.tcl 8.3b1 global local local global local global Have you identified what change in that time frame caused this bug? msofer added on 2001-05-03 21:36:41: Logged In: YES user_id=148712 Correction: the bug is exposed to tcl scripts ever since it was created in 8.1 - namespace eval does a direct evaluation only if it has multiple arguments. Therefore we should get in 8.1 (for the same definitions of unknown as in the original comment): % namespace eval mig aaa global % namespace eval mig aaa bbb local % namespace eval mig {aaa bbb} global msofer added on 2001-05-03 06:28:18: File Added - 5939: DIFF Logged In: YES user_id=148712 The enclosed patch "DIFF" restores the behaviour of 8.0, i.e., always call the global [unknown]. msofer added on 2001-05-02 23:06:22: Logged In: YES user_id=148712 As far as I can tell: (a) The bytecode engine has called the global [unknown] ever since 8.0 (see {generic/tclExecute.c: TclExecuteByteCode, INST_INVOKE} and {generic/tclBasic.c TclObjInvoke} (b) The inconsistency was introduced in 8.1, with the parser rewrite and the possibility of direct interpretation: the new procedure Tcl_EvalObjv calls the namespace [unknown], not the global one (c) The inconsistency was exposed to scripts in 8.3, with the "pure list optimisation" that allows a direct evaluation dgp added on 2001-05-02 03:25:45: Logged In: YES user_id=80530 The change in behavior occurred between Tcl releases 8.2.3 and 8.3b1. Using diffs, the ChangeLog, and 'cvs annotate', determine what code changes created the changed behavior, and who made them. Find out from them whether this was an intended effect (I doubt it). Unless they say yes, I think the change in behavior within the 8.x releases was a bug, and the 8.0 behavior should be restored. |
Attachments:
- DIFF [download] added by msofer on 2001-05-03 06:28:18. [details]