tclquadcode

Check-in [4f606de75c]
Login

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

Overview
Comment:Resolution context passed to invoke. Still need to stop quadcode engine from pre-resolving (at least in error cases).
Timelines: family | ancestors | descendants | both | fix-call-resolution
Files: files | file ages | folders
SHA3-256:4f606de75c689f4ad87f9176da90c4c10f8927f3fe94112c1b37936197540c65
User & Date: dkf 2017-12-20 09:25:27
Context
2017-12-23
08:40
Fix silly error. Closed-Leaf check-in: 2fc08314c2 user: dkf tags: minor change, unwanted
08:38
Trying to fix the resolution of commands to really happen at the right time. Leaf check-in: cd60d83f32 user: dkf tags: fix-call-resolution
2017-12-20
09:25
Resolution context passed to invoke. Still need to stop quadcode engine from pre-resolving (at least in error cases). check-in: 4f606de75c user: dkf tags: fix-call-resolution
2017-12-19
23:57
[7907c1c801] Make [dict update] work with NEXIST and ARRAY. check-in: 55314ea72f user: dkf tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to codegen/build.tcl.

4466
4467
4468
4469
4470
4471
4472

4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498

4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
    # Parameters:
    #	arguments -
    #		The arguments as an LLVM vector value reference. Note that
    #		this includes the function name as the first argument.
    #	havecf -
    #		Tcl boolean indicating if we have a valid callframe.
    #	cf -	The reference to the current callframe if 'havecf' is true.

    #	ec -	Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	resultName (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM value reference.

    method invoke {arguments havecf cf ec {resultName ""}} {
	my ExtractVector $arguments
	if {!$havecf} {
	    set cf {}
	}
	my call ${tcl.invoke.command} [list $len $ary $cf $ec] $resultName
    }

    # Builder:invokeExpanded --
    #
    #	Generate code to call a Tcl command while doing argument expansion.
    #	Quadcode implementation ('invokeExpanded').
    #
    # Parameters:
    #	arguments -
    #		The arguments as an LLVM vector value reference. Note that
    #		this includes the function name as the first argument.
    #	flags -	LLVM bit array indicating which arguments to expand.

    #	ec -	Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	resultName (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM value reference.

    method invokeExpanded {arguments flags ec {resultName ""}} {
	my ExtractVector $arguments
	my call ${tcl.invoke.expanded} [list $len $ary $flags $ec] $resultName
    }

    # Builder:isBoolean(INT BOOLEAN) --
    #
    #	Test if a value is a boolean. Quadcode implementation ('isBoolean').
    #
    # Parameters:







>








|




|












>








|

|







4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
    # Parameters:
    #	arguments -
    #		The arguments as an LLVM vector value reference. Note that
    #		this includes the function name as the first argument.
    #	havecf -
    #		Tcl boolean indicating if we have a valid callframe.
    #	cf -	The reference to the current callframe if 'havecf' is true.
    #	ns -	The official current namespace, as Namespace*.
    #	ec -	Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	resultName (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM value reference.

    method invoke {arguments havecf cf ns ec {resultName ""}} {
	my ExtractVector $arguments
	if {!$havecf} {
	    set cf {}
	}
	my call ${tcl.invoke.command} [list $len $ary $cf $ns $ec] $resultName
    }

    # Builder:invokeExpanded --
    #
    #	Generate code to call a Tcl command while doing argument expansion.
    #	Quadcode implementation ('invokeExpanded').
    #
    # Parameters:
    #	arguments -
    #		The arguments as an LLVM vector value reference. Note that
    #		this includes the function name as the first argument.
    #	flags -	LLVM bit array indicating which arguments to expand.
    #	ns -	The official current namespace, as Namespace*.
    #	ec -	Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	resultName (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM value reference.

    method invokeExpanded {arguments flags ns ec {resultName ""}} {
	my ExtractVector $arguments
	my call ${tcl.invoke.expanded} [list $len $ary $flags $ns $ec] $resultName
    }

    # Builder:isBoolean(INT BOOLEAN) --
    #
    #	Test if a value is a boolean. Quadcode implementation ('isBoolean').
    #
    # Parameters:

Changes to codegen/compile.tcl.

335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
...
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
....
1161
1162
1163
1164
1165
1166
1167


1168
1169
1170
1171
1172
1173
1174
1175
....
1224
1225
1226
1227
1228
1229
1230

1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243

1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
....
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
....
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
....
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
....
1352
1353
1354
1355
1356
1357
1358

1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
	    #

	    try {
	    $b @location $currentline
	    switch -exact -- [lindex $l 0 0] {
		"entry" {
		    lassign [my IssueEntry $l] \
			theframe thevarmap syntheticargs
		}
		"confluence" - "unset" {
		    # Do nothing; required for SSA computations only
		}
		"@debug-line" {
		    lassign $l opcode - srcfrom
		    set currentline [lindex $srcfrom 1]
................................................................................
			foreach {name value} $phiAnnotations {
			    my AnnotateAssignment $name $value
			}
			set phiAnnotations {}
		    }
		}
		"invoke" {
		    set arguments [my IssueInvoke $theframe $l]
		    foreach aa $arguments {
			set arguments [lassign $arguments a]
			if {$a ni $arguments && consumed($a, $pc + 1)} {
			    lappend consumed $a
			}
		    }
		}
		"invokeExpanded" {
		    set arguments [my IssueInvokeExpanded $theframe $l]
		    foreach aa $arguments {
			set arguments [lassign $arguments a]
			if {$a ni $arguments && consumed($a, $pc + 1)} {
			    lappend consumed $a
			}
		    }
		}
................................................................................
    #	exit.

    method IssueEntry {quad} {
	lassign $quad opcode tgt vars

	# When no frame is wanted
	if {$tgt eq {}} {


	    return [list [$b null CALLFRAME] {} {}]
	}

	# Store the fact that we must generate complex metadata for this
	# function/command, and the variable where this metadata will be
	# stored.
	if {![dict exists $bytecode procmeta]} {
	    dict set bytecode procmeta \
................................................................................
	set procmeta [dict get $bytecode procmeta]
	set localcache [dict get $bytecode localcache]
	lassign [$b frame.create $varmeta $argc $argv \
			[$b load $procmeta "proc.metadata"] \
			[$b load $localcache "proc.localcache"]] \
	    theframe thevarmap
	my StoreResult $tgt $theframe

	return [list $theframe $thevarmap $drop]
    }
 
    # TclCompiler:IssueInvoke --
    #
    #	Generate the code for invoking another Tcl command. Must only be
    #	called from the 'compile' method.
    #
    # Parameters:
    #	callframe -
    #		The callframe.
    #	operation -
    #		The quadcode descriptor for the instruction.

    #
    # Results:
    #	The set of arguments that might have been consumed in the operation
    #	(for cleanup by the caller of this method).

    method IssueInvoke {callframe operation} {
	set arguments [lassign $operation opcode tgt thecallframe origname]
	set vname [my LocalVarName $tgt]
	set BASETYPES {ZEROONE INT DOUBLE NUMERIC STRING}
	set resolved {}

	# Is this a literal name for a function we already know the signature
	# of? If so, we can use a direct call. To work this out, we need to
	# resolve the command within the namespace context of the procedure.

	if {literal($origname)} {
	    # Resolve the name.
................................................................................
	    }
	    if {[dict exist $vtypes $tgt]} {
		set type [nameOfType [dict get $vtypes $tgt]]
		if {"FAIL" ni $type || "STRING" ni $type} {
		    my Warn "didn't find implementation of '$fullname'"
		}
	    }
	    # Don't need to pre-resolve command names if there's a callframe
	    if {!callframe($thecallframe)} {
		set resolved [my LoadOrLiteral [list literal $name]]
	    }
	}

	set arguments [list $origname {*}$arguments]
	set argvals [lmap s $arguments {my LoadOrLiteral $s}]

	# Dynamic dispatch via direct call is OK, *provided* someone has
	# fetched the function reference for us.
................................................................................
	    return {}
	}

	# Must dispatch via the Tcl command API. This is the slowest option
	# with the least type inference possible (everything goes as a
	# STRING) but it is a reasonable fallback if nothing else works.

	my IssueInvokeCommand $tgt $resolved $arguments $argvals $vname
	return $arguments
    }

    method IssueInvokeFunction {tgt func arguments vname} {
	upvar 1 callframe callframe thecallframe thecallframe
	set BASETYPES {ZEROONE INT DOUBLE NUMERIC STRING}

................................................................................

	if {callframe($thecallframe)} {
	    set result [$b frame.pack $callframe $result]
	}
	my StoreResult $tgt $result
    }

    method IssueInvokeCommand {tgt resolved arguments argvals vname} {
	upvar 1 callframe callframe thecallframe thecallframe

	set types [lmap s $arguments {my ValueTypes $s}]
	if {$resolved ne ""} {
	    # FIXME: this causes wrong "wrong # args" messages
	    set argvals [lreplace $argvals 0 0 $resolved]
	}
	set vector [$b buildVector $types $argvals]
	set result [$b invoke $vector \
			[expr {callframe($thecallframe)}] $callframe \
			$errorCode $vname]
	$b clearVector $arguments $vector $types
	# Result type is now FAIL STRING, always.
	my SetErrorLine $errorCode [$b maybe $result]
	if {callframe($thecallframe)} {
	    set result [$b frame.pack $callframe $result]
	}
	my StoreResult $tgt $result
................................................................................
    #	Must only be called from the 'compile' method.
    #
    # Parameters:
    #	callframe -
    #		The callframe.
    #	operation -
    #		The quadcode descriptor for the instruction.

    #
    # Results:
    #	The set of arguments that might have been consumed in the operation
    #	(for cleanup by the caller of this method).

    method IssueInvokeExpanded {callframe operation} {
	set arguments [lassign $operation opcode tgt thecallframe]
	set vname [my LocalVarName $tgt]
	set expandPositions [lmap s $arguments {
	    expr {"EXPANDED" in [my OperandType $s]}
	}]
	set argvals [lmap s $arguments {my LoadOrLiteral $s}]
	set types [lmap s $arguments {my ValueTypes $s}]
	set vector [$b buildVector $types $argvals]
	set flags [$b buildBitArray $expandPositions]
	set result [$b invokeExpanded $vector $flags $errorCode $vname]
	my SetErrorLine $errorCode [$b maybe $result]
	my StoreResult $tgt [$b frame.pack $callframe $result]
	$b clearVector $arguments $vector $types
	return $arguments
    }
 
    # TclCompiler:IssueWiden --







|







 







|








|







 







>
>
|







 







>
|












>





|



<







 







<
<
<
<







 







|







 







|



<
<
<
<



|







 







>





|









|







335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
...
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
....
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
....
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256

1257
1258
1259
1260
1261
1262
1263
....
1271
1272
1273
1274
1275
1276
1277




1278
1279
1280
1281
1282
1283
1284
....
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
....
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330




1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
....
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
	    #

	    try {
	    $b @location $currentline
	    switch -exact -- [lindex $l 0 0] {
		"entry" {
		    lassign [my IssueEntry $l] \
			theframe thevarmap thens syntheticargs
		}
		"confluence" - "unset" {
		    # Do nothing; required for SSA computations only
		}
		"@debug-line" {
		    lassign $l opcode - srcfrom
		    set currentline [lindex $srcfrom 1]
................................................................................
			foreach {name value} $phiAnnotations {
			    my AnnotateAssignment $name $value
			}
			set phiAnnotations {}
		    }
		}
		"invoke" {
		    set arguments [my IssueInvoke $theframe $l $thens]
		    foreach aa $arguments {
			set arguments [lassign $arguments a]
			if {$a ni $arguments && consumed($a, $pc + 1)} {
			    lappend consumed $a
			}
		    }
		}
		"invokeExpanded" {
		    set arguments [my IssueInvokeExpanded $theframe $l $thens]
		    foreach aa $arguments {
			set arguments [lassign $arguments a]
			if {$a ni $arguments && consumed($a, $pc + 1)} {
			    lappend consumed $a
			}
		    }
		}
................................................................................
    #	exit.

    method IssueEntry {quad} {
	lassign $quad opcode tgt vars

	# When no frame is wanted
	if {$tgt eq {}} {
	    # FIXME: get namespace
	    set ns {}
	    return [list [$b null CALLFRAME] {} $ns {}]
	}

	# Store the fact that we must generate complex metadata for this
	# function/command, and the variable where this metadata will be
	# stored.
	if {![dict exists $bytecode procmeta]} {
	    dict set bytecode procmeta \
................................................................................
	set procmeta [dict get $bytecode procmeta]
	set localcache [dict get $bytecode localcache]
	lassign [$b frame.create $varmeta $argc $argv \
			[$b load $procmeta "proc.metadata"] \
			[$b load $localcache "proc.localcache"]] \
	    theframe thevarmap
	my StoreResult $tgt $theframe
	set thens [$b call dereference $theframe 0 CallFrame.nsPtr]
	return [list $theframe $thevarmap $thens $drop]
    }
 
    # TclCompiler:IssueInvoke --
    #
    #	Generate the code for invoking another Tcl command. Must only be
    #	called from the 'compile' method.
    #
    # Parameters:
    #	callframe -
    #		The callframe.
    #	operation -
    #		The quadcode descriptor for the instruction.
    #	thens -	The current namespace, used for command resolution.
    #
    # Results:
    #	The set of arguments that might have been consumed in the operation
    #	(for cleanup by the caller of this method).

    method IssueInvoke {callframe operation thens} {
	set arguments [lassign $operation opcode tgt thecallframe origname]
	set vname [my LocalVarName $tgt]
	set BASETYPES {ZEROONE INT DOUBLE NUMERIC STRING}


	# Is this a literal name for a function we already know the signature
	# of? If so, we can use a direct call. To work this out, we need to
	# resolve the command within the namespace context of the procedure.

	if {literal($origname)} {
	    # Resolve the name.
................................................................................
	    }
	    if {[dict exist $vtypes $tgt]} {
		set type [nameOfType [dict get $vtypes $tgt]]
		if {"FAIL" ni $type || "STRING" ni $type} {
		    my Warn "didn't find implementation of '$fullname'"
		}
	    }




	}

	set arguments [list $origname {*}$arguments]
	set argvals [lmap s $arguments {my LoadOrLiteral $s}]

	# Dynamic dispatch via direct call is OK, *provided* someone has
	# fetched the function reference for us.
................................................................................
	    return {}
	}

	# Must dispatch via the Tcl command API. This is the slowest option
	# with the least type inference possible (everything goes as a
	# STRING) but it is a reasonable fallback if nothing else works.

	my IssueInvokeCommand $tgt $arguments $argvals $thens $vname
	return $arguments
    }

    method IssueInvokeFunction {tgt func arguments vname} {
	upvar 1 callframe callframe thecallframe thecallframe
	set BASETYPES {ZEROONE INT DOUBLE NUMERIC STRING}

................................................................................

	if {callframe($thecallframe)} {
	    set result [$b frame.pack $callframe $result]
	}
	my StoreResult $tgt $result
    }

    method IssueInvokeCommand {tgt arguments argvals thens vname} {
	upvar 1 callframe callframe thecallframe thecallframe

	set types [lmap s $arguments {my ValueTypes $s}]




	set vector [$b buildVector $types $argvals]
	set result [$b invoke $vector \
			[expr {callframe($thecallframe)}] $callframe \
			$thens $errorCode $vname]
	$b clearVector $arguments $vector $types
	# Result type is now FAIL STRING, always.
	my SetErrorLine $errorCode [$b maybe $result]
	if {callframe($thecallframe)} {
	    set result [$b frame.pack $callframe $result]
	}
	my StoreResult $tgt $result
................................................................................
    #	Must only be called from the 'compile' method.
    #
    # Parameters:
    #	callframe -
    #		The callframe.
    #	operation -
    #		The quadcode descriptor for the instruction.
    #	thens -	The current namespace, used for command resolution.
    #
    # Results:
    #	The set of arguments that might have been consumed in the operation
    #	(for cleanup by the caller of this method).

    method IssueInvokeExpanded {callframe operation thens} {
	set arguments [lassign $operation opcode tgt thecallframe]
	set vname [my LocalVarName $tgt]
	set expandPositions [lmap s $arguments {
	    expr {"EXPANDED" in [my OperandType $s]}
	}]
	set argvals [lmap s $arguments {my LoadOrLiteral $s}]
	set types [lmap s $arguments {my ValueTypes $s}]
	set vector [$b buildVector $types $argvals]
	set flags [$b buildBitArray $expandPositions]
	set result [$b invokeExpanded $vector $flags $thens $errorCode $vname]
	my SetErrorLine $errorCode [$b maybe $result]
	my StoreResult $tgt [$b frame.pack $callframe $result]
	$b clearVector $arguments $vector $types
	return $arguments
    }
 
    # TclCompiler:IssueWiden --

Changes to codegen/stdlib.tcl.

4198
4199
4200
4201
4202
4203
4204
4205

4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216

4217
4218
4219
4220
4221
4222
4223
....
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
....
4308
4309
4310
4311
4312
4313
4314

4315
4316
4317
4318
4319
4320
4321
	    set NULL [my null Interp*]
	    set code [my setFromAny [$api tclBooleanType] $NULL $objPtr]
	    my ret [my eq $code $0]
	}

	##### Function tcl.invoke.command #####
	#
	# Type signature: objc:int * objv:STRING* * ecvar:int* -> STRING?

	#
	# Calls the Tcl interpreter to invoke a Tcl command, and packs the
	# result into a STRING FAIL.

	set f [$module local "tcl.invoke.command" \
		   STRING?<-int,STRING*,CALLFRAME,int*]
	params objc objv frame ecvar
	build {
	    noalias $objv $frame $ecvar
	    nonnull $objv $ecvar
	    set interp [$api tclInterp]

	    my condBr [my nonnull $frame] $frameInvoke $stdInvoke
	label stdInvoke "invoke.standard"
	    set code1 [$api Tcl_EvalObjv $interp $objc $objv $0]
	    my condBr [my eq $code1 $0] $ok $fail
	label frameInvoke "invoke.with.callframe"
	    set vfp [my gep $interp 0 Interp.varFramePtr]
	    set vf [my load $vfp]
................................................................................
	    set code [my phi [list $code1 $code2] [list $stdInvoke $frameInvoke] "code"]
	    my store $code $ecvar
	    my ret [my fail STRING $code]
	}

	##### Function tcl.invoke.expanded #####
	#
	# Type signature: objc:int * objv:STRING* * flags:bool* * ecvar:int*
	#			-> STRING?
	#
	# Calls the Tcl interpreter to invoke a Tcl command, first expanding
	# the arguments indicate by the flags array (which will have objc
	# elements in it), and packs the result into a STRING FAIL.

	set f [$module local "tcl.invoke.expanded" \
		   STRING?<-int,STRING*,bool*,int*]
	params objc objv flags ecvar
	build {
	    noalias $objv $flags $ecvar
	    nonnull $objv $flags $ecvar
	    set tclobjSize [my cast(int) [my sizeof STRING]]
	    set interp [$api tclInterp]
	    set iPtr [my alloc int "i"]
	    set jPtr [my alloc int "j"]
	    set lenPtr [my alloc int "len"]
	    set objcPtr [my alloc int "objcPtr"]
	    set objvPtr [my alloc STRING* "objvPtr"]
................................................................................
	    my store $obj $target
	    my store [my add $j $1] $jPtr
	    my br $expansionNext
	label expansionNext "next.expansion"
	    my store [my add $i $1] $iPtr
	    my br $expansionTest
	label invoke:

	    set code [$api Tcl_EvalObjv $interp $len $ary $0]
	    $api ckfree $ary
	    my condBr [my eq $code $0] $ok $fail
	label ok:
	    set result [$api Tcl_GetObjResult $interp]
	    my addReference(STRING) $result
	    my ret [my ok $result]







|
>





|
|

|
|

>







 







|
|






|
|

|
|







 







>







4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
....
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
....
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
	    set NULL [my null Interp*]
	    set code [my setFromAny [$api tclBooleanType] $NULL $objPtr]
	    my ret [my eq $code $0]
	}

	##### Function tcl.invoke.command #####
	#
	# Type signature: objc:int * objv:STRING* * nsptr:Namespace*
	#			* ecvar:int* -> STRING?
	#
	# Calls the Tcl interpreter to invoke a Tcl command, and packs the
	# result into a STRING FAIL.

	set f [$module local "tcl.invoke.command" \
		   STRING?<-int,STRING*,CALLFRAME,Namespace*,int*]
	params objc objv frame nsptr ecvar
	build {
	    noalias $objv $frame $nsptr $ecvar
	    nonnull $objv $nsptr $ecvar
	    set interp [$api tclInterp]
	    my storeInStruct $interp Interp.lookupNsPtr $nsptr
	    my condBr [my nonnull $frame] $frameInvoke $stdInvoke
	label stdInvoke "invoke.standard"
	    set code1 [$api Tcl_EvalObjv $interp $objc $objv $0]
	    my condBr [my eq $code1 $0] $ok $fail
	label frameInvoke "invoke.with.callframe"
	    set vfp [my gep $interp 0 Interp.varFramePtr]
	    set vf [my load $vfp]
................................................................................
	    set code [my phi [list $code1 $code2] [list $stdInvoke $frameInvoke] "code"]
	    my store $code $ecvar
	    my ret [my fail STRING $code]
	}

	##### Function tcl.invoke.expanded #####
	#
	# Type signature: objc:int * objv:STRING* * flags:bool*
	#			* nsptr:Namespace* * ecvar:int* -> STRING?
	#
	# Calls the Tcl interpreter to invoke a Tcl command, first expanding
	# the arguments indicate by the flags array (which will have objc
	# elements in it), and packs the result into a STRING FAIL.

	set f [$module local "tcl.invoke.expanded" \
		   STRING?<-int,STRING*,bool*,Namespace*,int*]
	params objc objv flags nsptr ecvar
	build {
	    noalias $objv $flags $nsptr $ecvar
	    nonnull $objv $flags $nsptr $ecvar
	    set tclobjSize [my cast(int) [my sizeof STRING]]
	    set interp [$api tclInterp]
	    set iPtr [my alloc int "i"]
	    set jPtr [my alloc int "j"]
	    set lenPtr [my alloc int "len"]
	    set objcPtr [my alloc int "objcPtr"]
	    set objvPtr [my alloc STRING* "objvPtr"]
................................................................................
	    my store $obj $target
	    my store [my add $j $1] $jPtr
	    my br $expansionNext
	label expansionNext "next.expansion"
	    my store [my add $i $1] $iPtr
	    my br $expansionTest
	label invoke:
	    my storeInStruct $interp Interp.lookupNsPtr $nsptr
	    set code [$api Tcl_EvalObjv $interp $len $ary $0]
	    $api ckfree $ary
	    my condBr [my eq $code $0] $ok $fail
	label ok:
	    set result [$api Tcl_GetObjResult $interp]
	    my addReference(STRING) $result
	    my ret [my ok $result]