Tcl Source Code

Check-in [be60dadb16]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:TIP#457: Update named group ending
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | tip-457
Files: files | file ages | folders
SHA1: be60dadb167c3a43a6f1ee59daf9a8d691f6c9d1
User & Date: mlafon 2017-05-23 22:36:27
Context
2017-05-23
22:36
TIP#457: Update named group ending Leaf check-in: be60dadb16 user: mlafon tags: tip-457
22:27
merge trunk check-in: 340fa5f4a8 user: mlafon tags: tip-457
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to doc/proc.n.

147
148
149
150
151
152
153


154
155
156
157
158


159
160




161
162




163
164
165
166
167
168
169
.SS "NAMED ARGUMENTS HANDLING"
.VS
.PP
Named argument are arguments defined using the \fB-name\fR or \fB-switch\fR
extended argument specifiers. They have a special handling on call-site.
All contiguous named arguments, called named group, are handled together,
they are not required to be declared in order, can be omited or declared


multiple times. The handling of a named group is started when previous
formal arguments have been assigned.
Each named parameter uses a string starting with a dash character, followed
by the name of the related argument. If it is not a switch argument, it is
followed by the value to assign to the formal argument. The handling of


a named group is ended if the next parameter is a multiple-elements list,
does not start with a dash or is the special \fB--\fR keyword. Remaining




parameters, except the \fB--\fR keyword if used, are then assigned to
following positional arguments using the default handling.




.VE
.SH EXAMPLES
.PP
This is a procedure that takes two arguments and prints both their sum
and their product. It also returns the string
.QW OK
to the caller as an explicit result.







>
>
|
|


|
>
>
|
|
>
>
>
>
|

>
>
>
>







147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
.SS "NAMED ARGUMENTS HANDLING"
.VS
.PP
Named argument are arguments defined using the \fB-name\fR or \fB-switch\fR
extended argument specifiers. They have a special handling on call-site.
All contiguous named arguments, called named group, are handled together,
they are not required to be declared in order, can be omited or declared
multiple times.
.PP
The handling of a named group is started when previous formal arguments have
been assigned.
Each named parameter uses a string starting with a dash character, followed
by the name of the related argument. If it is not a switch argument, it is
followed by the value to assign to the formal argument.
.PP
The handling of
a named group is ended if the next parameter does not start with a dash or is
the special \fB--\fR keyword. In the case where the arguments after the named
group are all non-optional positional arguments and do not end with \fBargs\fR,
the handling of the named group will also be ended when the number of remaining
parameters will be equal to the number of the remaining positional arguments.
When the handling of named argument has been ended, remaining parameters,
except the \fB--\fR keyword if used, are then assigned to
following positional arguments using the default handling.
.PP
It is recommended to explicitely use the \fB--\fR keyword if the next parameter
following the named group is a variable which may start with a dash, or if it
is an object which can be expensive to stringify.
.VE
.SH EXAMPLES
.PP
This is a procedure that takes two arguments and prints both their sum
and their product. It also returns the string
.QW OK
to the caller as an explicit result.
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
    {level -name level -switch {{debug 0} {error 3}} -default 1}
    {time -name {time timestamp}}
    {message} } {
  if {![info exists time]} {set time [clock seconds]}
  array set levels {0 DEBUG 1 INFO 2 WARN 3 ERROR}
  puts "[clock format $time] : $levels($level) : $message"
}

% log -level 2 "Warning..."
Sun Apr 23 20:29:41 UTC 2017 : WARN : Warning...
% log -timestamp 946684800 -debug -- -Y2K-
Sat Jan 01 00:00:00 UTC 2000 : DEBUG : -Y2K-
.CE
.SH "SEE ALSO"
info(n), unknown(n)
.SH KEYWORDS
argument, procedure
'\" Local Variables:
'\" mode: nroff
'\" End:







<
<
<
<
<








229
230
231
232
233
234
235





236
237
238
239
240
241
242
243
    {level -name level -switch {{debug 0} {error 3}} -default 1}
    {time -name {time timestamp}}
    {message} } {
  if {![info exists time]} {set time [clock seconds]}
  array set levels {0 DEBUG 1 INFO 2 WARN 3 ERROR}
  puts "[clock format $time] : $levels($level) : $message"
}





.CE
.SH "SEE ALSO"
info(n), unknown(n)
.SH KEYWORDS
argument, procedure
'\" Local Variables:
'\" mode: nroff
'\" End:

Changes to generic/tclInt.h.

943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958





959
960
961
962
963
964
965
 * The structure below describes an extended argument specification applied
 * on a proc argument (see TIP#457).
 */

typedef struct ExtendedArgSpec {
    struct NamedGroupEntry *firstNamedEntryPtr;
				/* Pointer to the first named parameter entry
				 * defined on the proc argument. */
    struct NamedGroupEntry *lastNamedEntryPtr;
				/* Pointer to the last named parameter entry
				 * defined on the proc argument. */
    Tcl_HashTable *namedHashTable;
				/* Pointer to the hash table created for a
				 * fast lookup of named entry. The pointer is
				 * only set on the first local of a named
				 * group. */





    Tcl_Obj *upvarLevelPtr;	/* Pointer to the level value specified using
				 * the -upvar specifier. */
} ExtendedArgSpec;

/*
 * The variable-length structure below describes a local variable of a
 * procedure that was recognized by the compiler. These variables have a name,







|
<
<
<





>
>
>
>
>







943
944
945
946
947
948
949
950



951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
 * The structure below describes an extended argument specification applied
 * on a proc argument (see TIP#457).
 */

typedef struct ExtendedArgSpec {
    struct NamedGroupEntry *firstNamedEntryPtr;
				/* Pointer to the first named parameter entry
				 * defined on this proc argument. */



    Tcl_HashTable *namedHashTable;
				/* Pointer to the hash table created for a
				 * fast lookup of named entry. The pointer is
				 * only set on the first local of a named
				 * group. */
    int remainAfterNamedGroup;	/* If the number of arguments after a named
				 * group is fixed and non-optional, this will
				 * contain that number. Otherwise, will be set
				 * to -1. This is only set on the first local
				 * of a named group. */
    Tcl_Obj *upvarLevelPtr;	/* Pointer to the level value specified using
				 * the -upvar specifier. */
} ExtendedArgSpec;

/*
 * The variable-length structure below describes a local variable of a
 * procedure that was recognized by the compiler. These variables have a name,
1046
1047
1048
1049
1050
1051
1052


1053
1054
1055

1056
1057
1058
1059
1060
1061
1062

/*
 * Flag bits for procedures.
 *
 * PROC_HAS_EXT_ARG_SPEC	1 means that the procedure has at least one
 *				argument defined using an extended argument
 *				specification.


 */

#define PROC_HAS_EXT_ARG_SPEC   0x01


/*
 * The type of functions called to process errors found during the execution
 * of a procedure (or lambda term or ...).
 */

typedef void (ProcErrorProc)(Tcl_Interp *interp, Tcl_Obj *procNameObj);







>
>



>







1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067

/*
 * Flag bits for procedures.
 *
 * PROC_HAS_EXT_ARG_SPEC	1 means that the procedure has at least one
 *				argument defined using an extended argument
 *				specification.
 * PROC_HAS_NAMED_GROUP		1 means that the procedure has at least one
 *				named group.
 */

#define PROC_HAS_EXT_ARG_SPEC   0x01
#define PROC_HAS_NAMED_GROUP    0x02

/*
 * The type of functions called to process errors found during the execution
 * of a procedure (or lambda term or ...).
 */

typedef void (ProcErrorProc)(Tcl_Interp *interp, Tcl_Obj *procNameObj);

Changes to generic/tclProc.c.

46
47
48
49
50
51
52




53
54
55
56
57
58
59
static void		ProcBodyFree(Tcl_Obj *objPtr);
static int		ProcWrongNumArgs(Tcl_Interp *interp, int skip);
static void		MakeProcError(Tcl_Interp *interp,
			    Tcl_Obj *procNameObj);
static void		MakeLambdaError(Tcl_Interp *interp,
			    Tcl_Obj *procNameObj);
static int		SetLambdaFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);




static int		ProcParseArgSpec(Tcl_Interp *interp,
			    const char *argSpec, int argIdx, int isLastArg,
			    CompiledLocal **localPtrPtr,
			    Tcl_HashTable **namedHashPtrPtr);
static inline int	ProcCheckScalarArg(const char *arg, const char **err);
static void		ProcCompiledLocalsFree(CompiledLocal *localPtr);








>
>
>
>







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
static void		ProcBodyFree(Tcl_Obj *objPtr);
static int		ProcWrongNumArgs(Tcl_Interp *interp, int skip);
static void		MakeProcError(Tcl_Interp *interp,
			    Tcl_Obj *procNameObj);
static void		MakeLambdaError(Tcl_Interp *interp,
			    Tcl_Obj *procNameObj);
static int		SetLambdaFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
static int		ProcAddNamedGroupEntry(Tcl_Interp *interp,
			    CompiledLocal *localPtr, const char *argName,
			    Tcl_Obj *valuePtr, NamedGroupEntry **lastEntryPtr,
			    Tcl_HashTable **namedHashPtrPtr);
static int		ProcParseArgSpec(Tcl_Interp *interp,
			    const char *argSpec, int argIdx, int isLastArg,
			    CompiledLocal **localPtrPtr,
			    Tcl_HashTable **namedHashPtrPtr);
static inline int	ProcCheckScalarArg(const char *arg, const char **err);
static void		ProcCompiledLocalsFree(CompiledLocal *localPtr);

581
582
583
584
585
586
587


588
589



































590
591
592
593
594
595
596
	    } else {
		procPtr->lastLocalPtr->nextPtr = newLocalPtr;
	    }
	    procPtr->lastLocalPtr = newLocalPtr;

	    if (TclIsVarWithExtArgs(newLocalPtr)) {
		procPtr->flags |= PROC_HAS_EXT_ARG_SPEC;


	    }
	}



































    }

    *procPtrPtr = procPtr;
    ckfree(argArray);
    return TCL_OK;

  procError:







>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
	    } else {
		procPtr->lastLocalPtr->nextPtr = newLocalPtr;
	    }
	    procPtr->lastLocalPtr = newLocalPtr;

	    if (TclIsVarWithExtArgs(newLocalPtr)) {
		procPtr->flags |= PROC_HAS_EXT_ARG_SPEC;
		if (newLocalPtr->flags & VAR_NAMED_GROUP) {
		    procPtr->flags |= PROC_HAS_NAMED_GROUP;
		}
	    }
	}
    }

    if ((procPtr->flags & PROC_HAS_NAMED_GROUP)
	    && !(procPtr->lastLocalPtr->flags & (VAR_IS_ARGS|VAR_ARG_OPTIONAL))
	    && (procPtr->lastLocalPtr->defValuePtr == NULL)) {

	/* proc with at least one named group and a non-optional and non-args
	 * last variable. Find and store the number of arguments after the
	 * last named group, this will be used to end the named group handling
	 * and ensure the last input arguments can be assigned.
	 */

	CompiledLocal *lastNamedGroupPtr = NULL;
	for (localPtr = procPtr->firstLocalPtr; localPtr != NULL;
		localPtr = localPtr->nextPtr) {
	    if ((localPtr->argSpecPtr != NULL)
		    && (localPtr->argSpecPtr->namedHashTable != NULL)) {
		lastNamedGroupPtr = localPtr;
	    }
	}

	/* find last entry of the named group */
	for (localPtr = lastNamedGroupPtr; localPtr != NULL;
		localPtr = localPtr->nextPtr) {
	    if ((localPtr->nextPtr == NULL)
		    || !(localPtr->nextPtr->flags & VAR_NAMED_GROUP)) {
		break;
	    }
	}

	if (localPtr != NULL) {
	    lastNamedGroupPtr->argSpecPtr->remainAfterNamedGroup =
		procPtr->lastLocalPtr->frameIndex - localPtr->frameIndex;
	}
    }

    *procPtrPtr = procPtr;
    ckfree(argArray);
    return TCL_OK;

  procError:
671
672
673
674
675
676
677
678


679
680
681
682
683
684
685
686
687
688
689



690
691
692
693
694
695
696
 * Results:
 *	Returns TCL_OK on success and TCL_ERROR if anything goes wrong.
 *
 * Side effects:
 *	If anything goes wrong, this function returns an error message in the
 *	interpreter. On success, memory is allocated and linked into the
 *	ExtendedArgSpec structure. A Tcl_HashTable is allocated when
 *	parsing the first entry of a named group entry.


 *
 *----------------------------------------------------------------------
 */

static int
ProcAddNamedGroupEntry(
    Tcl_Interp *interp,		/* Interpreter containing proc. */
    CompiledLocal *localPtr,	/* Related CompiledLocal */
    const char *argName,	/* Name string to add */
    Tcl_Obj *valuePtr,		/* Value to add when related to a -switch
				 * argspec (NULL for -name argspec) */



    Tcl_HashTable **namedHashPtrPtr)
				/* Shared Tcl_HashTable created on the first
				 * named parameter entry to speedup lookups
				 * of named parameters. */
{
    NamedGroupEntry *entryPtr;
    ExtendedArgSpec *argSpecPtr = localPtr->argSpecPtr;







|
>
>











>
>
>







712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
 * Results:
 *	Returns TCL_OK on success and TCL_ERROR if anything goes wrong.
 *
 * Side effects:
 *	If anything goes wrong, this function returns an error message in the
 *	interpreter. On success, memory is allocated and linked into the
 *	ExtendedArgSpec structure. A Tcl_HashTable is allocated when
 *	parsing the first entry of a named group entry. The variable pointed
 *	by lastEntryPtr will be updated to always contain the pointer
 *	of the last entry.
 *
 *----------------------------------------------------------------------
 */

static int
ProcAddNamedGroupEntry(
    Tcl_Interp *interp,		/* Interpreter containing proc. */
    CompiledLocal *localPtr,	/* Related CompiledLocal */
    const char *argName,	/* Name string to add */
    Tcl_Obj *valuePtr,		/* Value to add when related to a -switch
				 * argspec (NULL for -name argspec) */
    NamedGroupEntry **lastEntryPtr,
				/* Pointer to a variable which contain the current
				 * last named entry for this local. */
    Tcl_HashTable **namedHashPtrPtr)
				/* Shared Tcl_HashTable created on the first
				 * named parameter entry to speedup lookups
				 * of named parameters. */
{
    NamedGroupEntry *entryPtr;
    ExtendedArgSpec *argSpecPtr = localPtr->argSpecPtr;
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
    if (entryPtr->valuePtr != NULL) {
	Tcl_IncrRefCount(entryPtr->valuePtr);
    }

    if (argSpecPtr->firstNamedEntryPtr == NULL) {
	argSpecPtr->firstNamedEntryPtr = entryPtr;
    } else {
	argSpecPtr->lastNamedEntryPtr->nextPtr = entryPtr;
    }
    argSpecPtr->lastNamedEntryPtr = entryPtr;

    /* Either use existing hash table or create a new one */

    if (*namedHashPtrPtr != NULL) {
	namedHashPtr = *namedHashPtrPtr;
    }
    else {







|

|







776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
    if (entryPtr->valuePtr != NULL) {
	Tcl_IncrRefCount(entryPtr->valuePtr);
    }

    if (argSpecPtr->firstNamedEntryPtr == NULL) {
	argSpecPtr->firstNamedEntryPtr = entryPtr;
    } else {
	(*lastEntryPtr)->nextPtr = entryPtr;
    }
    *lastEntryPtr = entryPtr;

    /* Either use existing hash table or create a new one */

    if (*namedHashPtrPtr != NULL) {
	namedHashPtr = *namedHashPtrPtr;
    }
    else {
795
796
797
798
799
800
801

802
803
804
805
806
807
808
    Tcl_HashTable **namedHashPtrPtr)
				/* Shared Tcl_HashTable created on the first
				 * named parameter entry to speedup lookups
				 * of named parameters. */
{
    CompiledLocal *localPtr = NULL;
    ExtendedArgSpec *argSpecPtr;

    const char **fieldValues = NULL;
    int fieldCount, length;
    const char *err;
    int required = -1, hasSwitch = 0;
    int result, i, j;

    /*







>







841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
    Tcl_HashTable **namedHashPtrPtr)
				/* Shared Tcl_HashTable created on the first
				 * named parameter entry to speedup lookups
				 * of named parameters. */
{
    CompiledLocal *localPtr = NULL;
    ExtendedArgSpec *argSpecPtr;
    NamedGroupEntry *lastNamedEntryPtr = NULL;
    const char **fieldValues = NULL;
    int fieldCount, length;
    const char *err;
    int required = -1, hasSwitch = 0;
    int result, i, j;

    /*
869
870
871
872
873
874
875
876
877

878
879
880
881
882
883
884

    /*
     * Check and handle each extended argument specification.
     */

    argSpecPtr = ckalloc(sizeof(ExtendedArgSpec));
    argSpecPtr->firstNamedEntryPtr = NULL;
    argSpecPtr->lastNamedEntryPtr = NULL;
    argSpecPtr->namedHashTable = NULL;

    argSpecPtr->upvarLevelPtr = NULL;
    localPtr->argSpecPtr = argSpecPtr;

    for (i = 1 ; i < fieldCount ; i += 2) {
	length = strlen(fieldValues[i]);

	if (*fieldValues[i] != '-') {







<

>







916
917
918
919
920
921
922

923
924
925
926
927
928
929
930
931

    /*
     * Check and handle each extended argument specification.
     */

    argSpecPtr = ckalloc(sizeof(ExtendedArgSpec));
    argSpecPtr->firstNamedEntryPtr = NULL;

    argSpecPtr->namedHashTable = NULL;
    argSpecPtr->remainAfterNamedGroup = -1;
    argSpecPtr->upvarLevelPtr = NULL;
    localPtr->argSpecPtr = argSpecPtr;

    for (i = 1 ; i < fieldCount ; i += 2) {
	length = strlen(fieldValues[i]);

	if (*fieldValues[i] != '-') {
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
		    &nameValues);
	    if (result != TCL_OK) {
		goto parseError;
	    }

	    for (j = 0; j < nameCount; j++) {
		result = ProcAddNamedGroupEntry(interp, localPtr,
		    nameValues[j], NULL, namedHashPtrPtr);
		if (result != TCL_OK) {
		    ckfree(nameValues);
		    goto parseError;
		}
	    }

	    ckfree(nameValues);







|







964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
		    &nameValues);
	    if (result != TCL_OK) {
		goto parseError;
	    }

	    for (j = 0; j < nameCount; j++) {
		result = ProcAddNamedGroupEntry(interp, localPtr,
		    nameValues[j], NULL, &lastNamedEntryPtr, namedHashPtrPtr);
		if (result != TCL_OK) {
		    ckfree(nameValues);
		    goto parseError;
		}
	    }

	    ckfree(nameValues);
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
		    goto parseError;
		}

		if (swEntCount == 1) {
		    /* one field, use switch name as value */
		    result = ProcAddNamedGroupEntry(interp, localPtr,
			swEntValues[0], Tcl_NewStringObj(swEntValues[0], -1),
			namedHashPtrPtr);
		} else if (swEntCount == 2) {
		    /* two fields, use second one as value */
		    result = ProcAddNamedGroupEntry(interp, localPtr,
			swEntValues[0], Tcl_NewStringObj(swEntValues[1], -1),
			namedHashPtrPtr);
		} else {
		    /* invalid number of fields */
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"incorrect switch value \"%s\"", swValues[j]));
		    result = TCL_ERROR;
		}
		ckfree(swEntValues);







|




|







1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
		    goto parseError;
		}

		if (swEntCount == 1) {
		    /* one field, use switch name as value */
		    result = ProcAddNamedGroupEntry(interp, localPtr,
			swEntValues[0], Tcl_NewStringObj(swEntValues[0], -1),
			&lastNamedEntryPtr, namedHashPtrPtr);
		} else if (swEntCount == 2) {
		    /* two fields, use second one as value */
		    result = ProcAddNamedGroupEntry(interp, localPtr,
			swEntValues[0], Tcl_NewStringObj(swEntValues[1], -1),
			&lastNamedEntryPtr, namedHashPtrPtr);
		} else {
		    /* invalid number of fields */
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"incorrect switch value \"%s\"", swValues[j]));
		    result = TCL_ERROR;
		}
		ckfree(swEntValues);
2060
2061
2062
2063
2064
2065
2066
2067

2068


2069
2070

2071
2072
2073
2074
2075
2076
2077

	    /*
	     * Start of a named argument group. Handle all of them together.
	     */

	    for (; iArg < argCt; iArg++) {

		if ((argObjs[iArg]->typePtr == &tclListType)

			&& (ListRepPtr(argObjs[iArg])->elemCount > 1)) {


		    /* multiple-elements list, end named group before getting
		     * string representation. */

		    break;
		}

		optStr = TclGetString(argObjs[iArg]);

		if (*optStr != '-') {
		    /* argument without leading dash, end named group */







|
>
|
>
>
|
<
>







2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119

2120
2121
2122
2123
2124
2125
2126
2127

	    /*
	     * Start of a named argument group. Handle all of them together.
	     */

	    for (; iArg < argCt; iArg++) {

		if ((localPtr->argSpecPtr != NULL)
			&& (localPtr->argSpecPtr->remainAfterNamedGroup > 0)
			&& ((argCt - iArg) <=
			    localPtr->argSpecPtr->remainAfterNamedGroup)) {
		    /* Remaining arguments must be assigned to remaining
		     * positional locals after named group, end handling

		     */
		    break;
		}

		optStr = TclGetString(argObjs[iArg]);

		if (*optStr != '-') {
		    /* argument without leading dash, end named group */

Changes to tests/proc-enh.test.

176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
} {{0 B 5 D E} {0 0 foo 0 E}}
test proc-enh-2.14 {correct usage: named arg without required is optionnal} {
    proc p {{a -name A}} {
	if {[info exists a]} { return $a } else { return unset }
    };
    list [p] [p -A 2]
} {unset 2}
test proc-enh-2.15 {correct usage: multi-elems list must not be handled as a named name} {
    proc p {{a -name A -default 0} b} {
	list $a $b
    };
    set l [list -Z 1]
    p $l
} {0 {-Z 1}}

# proc-enh-3.x: wrong # args
test proc-enh-3.1 {wrong # args: -name arg without value} {
    proc p {{a -name A} {b -name B -default 1}} { }
    list [catch { p -A } msg] $msg $errorCode
} {1 {wrong # args: should be "p ?|-A a|? ?|-B b|?"} {TCL WRONGARGS}}
test proc-enh-3.2 {wrong # args: named group ended by an arg with leading dash} {







|
|
|


|
|







176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
} {{0 B 5 D E} {0 0 foo 0 E}}
test proc-enh-2.14 {correct usage: named arg without required is optionnal} {
    proc p {{a -name A}} {
	if {[info exists a]} { return $a } else { return unset }
    };
    list [p] [p -A 2]
} {unset 2}
test proc-enh-2.15 {correct usage: fixed number of arguments after named group, automatically ended} {
    proc p {{a -name A -default 0} {b -name B -default 0} c} {
	list $a $b $c
    };
    set l [list -Z 1]
    list [p -2] [p -A 1 -5] [p -- -3] [p --]
} {{0 0 -2} {1 0 -5} {0 0 -3} {0 0 --}}

# proc-enh-3.x: wrong # args
test proc-enh-3.1 {wrong # args: -name arg without value} {
    proc p {{a -name A} {b -name B -default 1}} { }
    list [catch { p -A } msg] $msg $errorCode
} {1 {wrong # args: should be "p ?|-A a|? ?|-B b|?"} {TCL WRONGARGS}}
test proc-enh-3.2 {wrong # args: named group ended by an arg with leading dash} {