Check-in [9f6d191beb]

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

Overview
Comment:Add support for invoking non-compiled Tcl commands using NRE. Still have to do invokeExpanded.
Timelines: family | ancestors | descendants | both | kbk-nre
Files: files | file ages | folders
SHA3-256:9f6d191bebefe571ca702c7d9ff9055611bf31c89f622d0dc7326e7f12050e27
User & Date: kbk 2018-05-02 05:28:28
Context
2018-10-21
16:12
merge trunk check-in: 3c382b2d30 user: dkf tags: kbk-nre
2018-05-02
05:28
Add support for invoking non-compiled Tcl commands using NRE. Still have to do invokeExpanded. check-in: 9f6d191beb user: kbk tags: kbk-nre
2018-05-01
02:13
Make sure that local vars are located on the coro frame and not on the stack. Fix a spurious error when an 'upvar' follows a 'moveToCallFrame' for a nonexistent local var. check-in: 2945c2321c user: kbk tags: kbk-nre
Changes

Changes to codegen/build.tcl.

4505
4506
4507
4508
4509
4510
4511




























4512
4513
4514
4515
4516
4517
4518
    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:







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
    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:invokeNRE --
    #
    #	Generate code to call a Tcl command with non-recursive eval.
    # Quadcode implementation ('NRE.invoke').
    #
    # Parameters:
    #	arguments -
    #		The arguments as an LLVM array 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 invokeNRE {arguments havecf cf ec {resultName ""}} {
	my ExtractVector $arguments
	if {!$havecf} {
	    set cf {}
	}
	my call ${tcl.invoke.command.nre} [list $len $ary $cf $ec] $resultName
    }

    # Builder:invokeExpanded --
    #
    #	Generate code to call a Tcl command while doing argument expansion.
    #	Quadcode implementation ('invokeExpanded').
    #
    # Parameters:

Changes to codegen/compile.tcl.

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
....
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
....
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
....
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
....
1346
1347
1348
1349
1350
1351
1352























1353
1354
1355
1356
1357
1358
1359
....
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452





1453
1454
1455
1456








1457
1458
1459
1460
1461
1462
1463
....
1475
1476
1477
1478
1479
1480
1481





1482
1483
1484
1485
1486
1487
1488
#	none

oo::class create TclCompiler {
    superclass llvmEntity
    variable bytecode cmd func quads paramTypes returnType vtypes variables
    variable m b pc errorCode currentline currentprocrelline currentscript
    variable bytecodeVars namespace objv bitv
    variable nreReturnType

    constructor {} {
	next
	namespace import \
	    ::quadcode::nameOfType \
	    ::quadcode::typeOfLiteral \
	    ::quadcode::typeOfOperand \
................................................................................
	set procmeta [dict get $bytecode procmeta]
	set localcache [dict get $bytecode localcache]
	set callframe [$b allocInBlock $entryBlock CallFrame "callframe"]

	lassign [$b frame.create $varmeta $argc $argv \
		     [$b load $procmeta "proc.metadata"] \
		     [$b load $localcache "proc.localcache"] \
		    $callframe $entryBlock] \
	    theframe thevarmap
	my StoreResult $tgt $theframe
	return [list $theframe $thevarmap $drop]
    }
 
    # TclCompiler:IssueInvoke --
    #
................................................................................
    #	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 IssueNREInvoke {callframe operation} {

	set arguments [lassign $operation opcode tgt thecallframe origname]
	set rettype [lindex $opcode 1]
	set vname [my LocalVarName $tgt]

................................................................................
	set called [my ResolveInvoke $rettype $origname $arguments]
	if {$called ne {}} {
	    set argvals [lmap arg $arguments {my LoadOrLiteral $arg}]
	    set useCallframe [expr {callframe($thecallframe)}]
	    set handle [my IssueNREInvokeFunction \
			    $useCallframe $callframe \
			    $rettype $tgt $called $argvals $vname]
	    return {}
	} else {
	    set arguments [linsert $arguments[set arguments ""] 0 $origname]
	    set argvals [lmap arg $arguments {my LoadOrLiteral $arg}]
	    my IssueNREInvokeCommand $rettype $tgt $arguments $argvals $vname
	    return $arguments
	}
    }

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

	set types [lmap s $arguments {my ValueTypes $s}]
................................................................................
	set vector [$b buildVector $objv $types $arguments $argvals]
	set result [$b invoke $vector \
			[expr {callframe($thecallframe)}] $callframe \
			$errorCode $vname]
	$b clearVector $objv $types $arguments
	# 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
    }

    # TclCompiler:IssueInvokeExpanded --
................................................................................

    method IssueNREReturnFromInvoke {callframe operation} {

	set arguments [lassign $operation opcode tgt corohandle origname]
	set rettype [dict get $vtypes $tgt]
	set vname [my LocalVarName $tgt]
	set called [my ResolveInvoke $rettype $origname $arguments]
	if {$called ne {}} {
	    my IssueNREReturnFromInvokedFunction \
		$rettype $tgt $corohandle $callframe $vname
	    return {}
	} else {
	    set arguments [linsert $arguments[set arguments ""] 0 $origname]
	    set i -1
	    my IssueNREReturnFromInvokedCommand \
		$rettype $tgt $corohandle $callframe $arguments $vname
	    ;				# objc will still contain
	    ;				# argument values
	    return $arguments
	    ;				# FIXME: gotta work through the
	    ;			 	# refcounting 
	}
    }
 
    # TclCompiler:IssueNREReturnFromInvokedFunction --
    #
    #	Generates code to return from compiled NRE code.
    #
    # Parameters:
    #	rettype - Return type of the function
    #   tgt - Quadcode value representing the return value
    #	corohandle - Coroutine handle of the function that's just returned
    #	callframe - The current callframe
    #	origname - Quadcode value giving the name of the function
    #   arguments - List of quadcode values representing the arguments
    #	vname - LLVM name to assign to the result of the call
    #
    # Results:
    #	None.

    method IssueNREReturnFromInvokedFunction {rettype tgt corohandle callframe
					      vname} {

	# Built-in types that are handled here.
	set BASETYPES {ZEROONE INT DOUBLE NUMERIC STRING}
	set ts [lmap t $BASETYPES {Type $t?}]
	set tgttype [my ValueTypes $tgt]






	# Emit the sequence that destroys the LLVM coroutine and returns the
	# result as 'retval'
	lassign [my returnedFromCoro $rettype $tgttype $corohandle] \
	    callframe retcode retval









	# Handle the return

	if {$tgttype eq "FAIL"} {
	    # This procedure only ever fails.
	    $b store $retval $errorCode
	    my SetErrorLine $errorCode
................................................................................
	# Pack a callframe reference with the return if needed

	if {"CALLFRAME" in $tgttype} {
	    set retval [$b frame.pack $callframe $retval]
	}

	my StoreResult $tgt $retval





    }
 
    # TclCompiler:ResolveInvoke --
    #
    #	Determines whether an invoked command is known as a compiled
    #	function, and resolves it if it is.
    #







|







 







|







 







<
<
<
<







 







<



|
<







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






>
>
>
>
>


|

>
>
>
>
>
>
>
>







 







>
>
>
>
>







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
....
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
....
1304
1305
1306
1307
1308
1309
1310




1311
1312
1313
1314
1315
1316
1317
....
1318
1319
1320
1321
1322
1323
1324

1325
1326
1327
1328

1329
1330
1331
1332
1333
1334
1335
....
1340
1341
1342
1343
1344
1345
1346
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
....
1422
1423
1424
1425
1426
1427
1428



































1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
....
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
#	none

oo::class create TclCompiler {
    superclass llvmEntity
    variable bytecode cmd func quads paramTypes returnType vtypes variables
    variable m b pc errorCode currentline currentprocrelline currentscript
    variable bytecodeVars namespace objv bitv
    variable nreReturnType coro_info

    constructor {} {
	next
	namespace import \
	    ::quadcode::nameOfType \
	    ::quadcode::typeOfLiteral \
	    ::quadcode::typeOfOperand \
................................................................................
	set procmeta [dict get $bytecode procmeta]
	set localcache [dict get $bytecode localcache]
	set callframe [$b allocInBlock $entryBlock CallFrame "callframe"]

	lassign [$b frame.create $varmeta $argc $argv \
		     [$b load $procmeta "proc.metadata"] \
		     [$b load $localcache "proc.localcache"] \
		     $callframe $entryBlock] \
	    theframe thevarmap
	my StoreResult $tgt $theframe
	return [list $theframe $thevarmap $drop]
    }
 
    # TclCompiler:IssueInvoke --
    #
................................................................................
    #	called from the 'compile' method.
    #
    # Parameters:
    #	callframe -
    #		The callframe.
    #	operation -
    #		The quadcode descriptor for the instruction.





    method IssueNREInvoke {callframe operation} {

	set arguments [lassign $operation opcode tgt thecallframe origname]
	set rettype [lindex $opcode 1]
	set vname [my LocalVarName $tgt]

................................................................................
	set called [my ResolveInvoke $rettype $origname $arguments]
	if {$called ne {}} {
	    set argvals [lmap arg $arguments {my LoadOrLiteral $arg}]
	    set useCallframe [expr {callframe($thecallframe)}]
	    set handle [my IssueNREInvokeFunction \
			    $useCallframe $callframe \
			    $rettype $tgt $called $argvals $vname]

	} else {
	    set arguments [linsert $arguments[set arguments ""] 0 $origname]
	    set argvals [lmap arg $arguments {my LoadOrLiteral $arg}]
	    my IssueNREInvokeCommand $tgt $called $arguments $argvals $vname

	}
    }

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

	set types [lmap s $arguments {my ValueTypes $s}]
................................................................................
	set vector [$b buildVector $objv $types $arguments $argvals]
	set result [$b invoke $vector \
			[expr {callframe($thecallframe)}] $callframe \
			$errorCode $vname]
	$b clearVector $objv $types $arguments
	# 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
    }

    method IssueNREInvokeCommand {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 $objv $types $arguments $argvals]
	$b invokeNRE $vector [expr {callframe($thecallframe)}] \
	    $callframe $errorCode $vname

	# For an invoked command, we didn't launch another LLVM coroutine,
	# and the Tcl status and command return value will appear
	# in the current coroutine's promise.

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

    # TclCompiler:IssueInvokeExpanded --
................................................................................

    method IssueNREReturnFromInvoke {callframe operation} {

	set arguments [lassign $operation opcode tgt corohandle origname]
	set rettype [dict get $vtypes $tgt]
	set vname [my LocalVarName $tgt]
	set called [my ResolveInvoke $rettype $origname $arguments]




































	# Built-in types that are handled here.
	set BASETYPES {ZEROONE INT DOUBLE NUMERIC STRING}
	set ts [lmap t $BASETYPES {Type $t?}]
	set tgttype [my ValueTypes $tgt]

	if {$called ne {}} {
	    set destroy 1
	} else {
	    set destroy 0
	}
	# Emit the sequence that destroys the LLVM coroutine and returns the
	# result as 'retval'
	lassign [my returnedIntoCoro $rettype $tgttype $corohandle $destroy] \
	    callframe retcode retval

	# Clean up the arguments if needed

	if {$called eq {}} {
	    set arguments [linsert $arguments[set arguments ""] 0 $origname]
	    set types [lmap s $arguments {my ValueTypes $s}]
	    $b clearVector $objv $types $arguments
	}

	# Handle the return

	if {$tgttype eq "FAIL"} {
	    # This procedure only ever fails.
	    $b store $retval $errorCode
	    my SetErrorLine $errorCode
................................................................................
	# Pack a callframe reference with the return if needed

	if {"CALLFRAME" in $tgttype} {
	    set retval [$b frame.pack $callframe $retval]
	}

	my StoreResult $tgt $retval
	if {$called eq {}} {
	    return $arguments
	} else {
	    return {}
	}
    }
 
    # TclCompiler:ResolveInvoke --
    #
    #	Determines whether an invoked command is known as a compiled
    #	function, and resolves it if it is.
    #

Changes to codegen/coro.tcl.

357
358
359
360
361
362
363
364
365
366
367

368
369
370
371




372
373
374
375
376
377

378
379
380
381
382
383
384
...
391
392
393
394
395
396
397
398
399
400
401
402



403







404
405
406
407
408
















409
410
411
412
413
414
415
    while {[llength $argv] < 4} {
	lappend argv [my null int8*]
    }
    my call ${tcl.nr.add.callback} [linsert $argv 0 $func]
}
oo::define Builder export NRAddCallback
 
# TclCompiler method returnFromCoro --
#
#	Generates code to retrieve the status and return value from
#	a coroutine that has done the final suspend.

#
# Parameters:
#	rettype - The function's return type
#	callee - The name of the function that has been called




#
# Results:
#	Returns a list of two LLVM value refs: the status code and the
#	return value.

oo::define TclCompiler method returnedFromCoro {rettype tgttype corohandle} {


    # Retrieve the coroutine promise from the coroutine handle

    set handle [my LoadOrLiteral $corohandle]
    set frame {}
    if {"CALLFRAME" in $tgttype} {
	set frame [$b frame.frame $handle]
................................................................................
		       "promise.addr.raw"]
    set paddr [$b cast(ptr) $paddr_raw $ptype "promise.addr"]

    # Retrieve the return code and return value of the called procedure

    set rcodeaddr [$b gep $paddr 0 0]
    set rcode [$b load $rcodeaddr "return.code"]
    set rvaladdr [$b gep $paddr 0 1]
    set rval [$b load $rvaladdr "return.value"]

    # Destroy the coroutine - we're done with it now.




    $b call [$m intrinsic coro.destroy] [list $handle]








    # Return the status and result

    return [list $frame $rcode $rval]
}
















 
# TclCompiler method NRReturnToThunk --
#
#	Generates the codeburst to return to a call thunk when a compiled
#	NRE procedure returns.
#
# Parameters:







|


|
>



|
>
>
>
>





|
>







 







<
<



>
>
>
|
>
>
>
>
>
>
>





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
...
397
398
399
400
401
402
403


404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
    while {[llength $argv] < 4} {
	lappend argv [my null int8*]
    }
    my call ${tcl.nr.add.callback} [linsert $argv 0 $func]
}
oo::define Builder export NRAddCallback
 
# TclCompiler method returnedIntoCoro --
#
#	Generates code to retrieve the status and return value from
#	a coroutine that has done the final suspend or an invoked NRE
#	command.
#
# Parameters:
#	rettype - The function's return type
#	tgttype - The type of the target value
#	corohandle - The handle to the coroutine that ran the invoked function
#	destroy - Flag == 1 if this was a return from another coroutine
#	          that must be destroyed, 0 if it's a return from a
#		  Tcl_NRAddCallback chain in the same coroutine
#
# Results:
#	Returns a list of two LLVM value refs: the status code and the
#	return value.

oo::define TclCompiler method returnedIntoCoro {rettype tgttype 
						corohandle destroy} {

    # Retrieve the coroutine promise from the coroutine handle

    set handle [my LoadOrLiteral $corohandle]
    set frame {}
    if {"CALLFRAME" in $tgttype} {
	set frame [$b frame.frame $handle]
................................................................................
		       "promise.addr.raw"]
    set paddr [$b cast(ptr) $paddr_raw $ptype "promise.addr"]

    # Retrieve the return code and return value of the called procedure

    set rcodeaddr [$b gep $paddr 0 0]
    set rcode [$b load $rcodeaddr "return.code"]



    # Destroy the coroutine - we're done with it now.

    if {$destroy} {
	set rvaladdr [$b gep $paddr 0 1]
	set rval [$b load $rvaladdr "return.value"]
	$b call [$m intrinsic coro.destroy] [list $handle]
    } else {
	set rval [$b getNRCommandReturnValue $rcode $errorCode "return.value"]
	if {"CALLFRAME" in $tgttype} {
	    # Return from an invoked function may need to restore the callframe
	    $b restoreFrame
	}
    }

    # Return the status and result

    return [list $frame $rcode $rval]
}
 
# Builder method getNRCommandReturnValue --
#
#	Retrieves the return value of a noncompiled command invoked by NRE
#
# Parameters:
#	rcode - Return code of the invoked command
#	ecvar - LLVM variable reference of where to put the return code
#	name - (Optional) name to assign to the result
#
# Results:
#	Returns an LLVM STRING? value

oo::define Builder method getNRCommandReturnValue {rcode ecvar {name {}}} {
    my call ${tcl.nr.command.result} [list $rcode $ecvar] $name
}
 
# TclCompiler method NRReturnToThunk --
#
#	Generates the codeburst to return to a call thunk when a compiled
#	NRE procedure returns.
#
# Parameters:

Changes to codegen/stdlib.tcl.

55
56
57
58
59
60
61
62


63
64
65
66
67
68
69
....
4369
4370
4371
4372
4373
4374
4375






















































4376
4377
4378
4379
4380
4381
4382
....
4458
4459
4460
4461
4462
4463
4464

















4465
4466
4467
4468
4469
4470
4471
    variable tcl.dict.get1.empty tcl.dict.set1.empty
    variable tcl.maptoint

    # Variables holding implementations of Tcl's exception-handling machinery
    variable tcl.getresult tcl.getreturnopts tcl.initExceptionOptions
    variable tcl.initExceptionSimple tcl.processReturn tcl.procedure.return
    variable tcl.setErrorLine tcl.existsOrError tcl.logCommandInfo
    variable tcl.handleExceptionResult tcl.invoke.command tcl.invoke.expanded



    # Helper functions
    variable tcl.impl.trimleft tcl.impl.trimright obj.cleanup
    variable tcl.impl.getIndex tcl.impl.listDupe
    variable tcl.alloc tcl.free
    variable tcl.vector.clear

................................................................................
	    my addReference(STRING) $result
	    my ret [my ok $result]
	label fail:
	    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
................................................................................
	    set result [$api Tcl_GetObjResult $interp]
	    my addReference(STRING) $result
	    my ret [my ok $result]
	label fail:
	    my store $code $ecvar
	    my ret [my fail STRING $code]
	}


















	##### Function tcl.existsOrError #####
	#
	# Type signature: exists:int1 * message:STRING * ecvar:int* -> int1
	#
	# Conditionally generates an error about a non-existing variable.
	# Generated like this to avoid introducing extra basic blocks at the







|
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
....
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
....
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
    variable tcl.dict.get1.empty tcl.dict.set1.empty
    variable tcl.maptoint

    # Variables holding implementations of Tcl's exception-handling machinery
    variable tcl.getresult tcl.getreturnopts tcl.initExceptionOptions
    variable tcl.initExceptionSimple tcl.processReturn tcl.procedure.return
    variable tcl.setErrorLine tcl.existsOrError tcl.logCommandInfo
    variable tcl.handleExceptionResult tcl.invoke.command
    variable tcl.invoke.command.nre tcl.nr.command.result tcl.invoke.expanded
    variable tcl.restoreFrame

    # Helper functions
    variable tcl.impl.trimleft tcl.impl.trimright obj.cleanup
    variable tcl.impl.getIndex tcl.impl.listDupe
    variable tcl.alloc tcl.free
    variable tcl.vector.clear

................................................................................
	    my addReference(STRING) $result
	    my ret [my ok $result]
	label fail:
	    set code [my phi [list $code1 $code2] [list $stdInvoke $frameInvoke] "code"]
	    my store $code $ecvar
	    my ret [my fail STRING $code]
	}

	##### Function tcl.invoke.command.nre #####
	#
	# Type signature: objc:int × objv:STRING* × frame:CALLFRAME × ecvar:int*
	#                        -> CALLFRAME
	#
	# Calls the Tcl interpreter to invoke a Tcl command by means of
	# Tcl_NREvalObjv.
	#
	# Returns the callframe before the invocation if the callframe was
	# swizzled to do the invoke, NULL otherwise.

	set f [$module local "tcl.invoke.command.nre" \
		   CALLFRAME<-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"
	    $api Tcl_NREvalObjv $interp $objc $objv $0
	    my ret [my null CALLFRAME]
	label frameInvoke "invoke.with.callframe"
	    set vfp [my gep $interp 0 Interp.varFramePtr]
	    set vf [my load $vfp]
	    my store $frame $vfp
	    $api Tcl_NREvalObjv $interp $objc $objv $0
	    my ret $vf
	}

	##### Function tcl.nr.command.result #####
	#
	# Retrieves the value of a command invoked by tcl.invoke.command.nre
	# after the command has returned.
	#
	# Type signature: ecode:int × ecvar:int* -> STRING?

	set f [$module local "tcl.nr.command.result" STRING?<-int,int*]
	params ecode ecvar
	build {
	    noalias $ecvar
	    nonnull $ecvar
	    my condBr [my eq $ecode $0] $ok $fail
	label ok:
	    set result [$api Tcl_GetObjResult [$api tclInterp]]
	    my addReference(STRING) $result
	    my ret [my ok $result]
	label fail:
	    my store $ecode $ecvar
	    my ret [my fail STRING $ecode]

	}


	##### 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
................................................................................
	    set result [$api Tcl_GetObjResult $interp]
	    my addReference(STRING) $result
	    my ret [my ok $result]
	label fail:
	    my store $code $ecvar
	    my ret [my fail STRING $code]
	}

	##### Function tcl.restoreFrame #####
	#
	# Type signature: frame:CALLFRAME->void
	#
	# Restores the callframe pointer when returning from a Tcl_NRAddCallback
	# chain.

	set f [$module local "tcl.restoreFrame" void<-CALLFRAME]
	params frame
	build {
	    nonnull $frame
	    set interp [$api tclInterp]
	    set vfp [my gep $interp 0 Interp.varFramePtr]
	    my store $frame $vfp
	    my ret
	}

	##### Function tcl.existsOrError #####
	#
	# Type signature: exists:int1 * message:STRING * ecvar:int* -> int1
	#
	# Conditionally generates an error about a non-existing variable.
	# Generated like this to avoid introducing extra basic blocks at the

Changes to demos/perftest/tester.tcl.

1289
1290
1291
1292
1293
1294
1295




1296
1297
1298
1299
1300
1301
1302
....
2235
2236
2237
2238
2239
2240
2241

2242
2243
2244
2245
2246
2247
2248
....
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
    upvar 1 $nv nn
    if {[incr nn -1] <= 0} {
	return |
    } else {
	return .[rectest3 nn]
    }
}





proc treecollect {t} {
    set l {}
    treewalk l $t
    return $l
}
proc treewalk {lvar t} {
................................................................................
    {singleton::lforeach}
    {singleton::llindex}
    {singleton::srange}
    {rectest1}
    {treecollect {a {b {d {h i}} {e {j k}}} {c {f {l m}} {g {n o}}}}}
    {list [catch rectest2 result] $result}
    {set x 3; rectest3 x}

    {qsort {3 6 8 7 0 1 4 2 9 5}}
    {impure 0x0 0 0}
    {impure 0x3 0 0}
    {impure 0 1 1}
    {impure 10 10000 10}
    {impure 1 +2000 [string range "123" 2 2]}
    {impure-typecheck-int 10 10000 10}
................................................................................

    # Combined feature tests
    lcmRange
    bug-0616bcf08e::*
    rectest1
    rectest2
    rectest3
    # treecollect   Not working - upvar in NRE proc
    treecollect
    # treewalk      Not working - upvar in NRE proc
    treewalk
    qsort
    impure
    impure-caller
    impure-typecheck-int
    impure2
    comps







>
>
>
>







 







>







 







|

<







1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
....
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
....
2442
2443
2444
2445
2446
2447
2448
2449
2450

2451
2452
2453
2454
2455
2456
2457
    upvar 1 $nv nn
    if {[incr nn -1] <= 0} {
	return |
    } else {
	return .[rectest3 nn]
    }
}

proc openclose {} {
    close [open /dev/null w]
}

proc treecollect {t} {
    set l {}
    treewalk l $t
    return $l
}
proc treewalk {lvar t} {
................................................................................
    {singleton::lforeach}
    {singleton::llindex}
    {singleton::srange}
    {rectest1}
    {treecollect {a {b {d {h i}} {e {j k}}} {c {f {l m}} {g {n o}}}}}
    {list [catch rectest2 result] $result}
    {set x 3; rectest3 x}
    {openclose}
    {qsort {3 6 8 7 0 1 4 2 9 5}}
    {impure 0x0 0 0}
    {impure 0x3 0 0}
    {impure 0 1 1}
    {impure 10 10000 10}
    {impure 1 +2000 [string range "123" 2 2]}
    {impure-typecheck-int 10 10000 10}
................................................................................

    # Combined feature tests
    lcmRange
    bug-0616bcf08e::*
    rectest1
    rectest2
    rectest3
    openclose
    treecollect

    treewalk
    qsort
    impure
    impure-caller
    impure-typecheck-int
    impure2
    comps

Changes to quadcode/builtins.tcl.

1
2
3
4
5
6
7
8
..
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
...
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
# CREATED BY ./parseBuiltinsTxt.tcl, DO NOT EDIT
#
#-----------------------------------------------------------------------------
#
#-----------------------------------------------------------------------------
#
# builtins.tcl.in --
#
................................................................................
    dict set cmdAttr ::after \
        {noCallFrame {}}
    dict set cmdAttr ::cd \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::clock \
        {special {}}
    dict set cmdAttr ::close \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::encoding \
        [dict get $cmdAttr ::clock]
    dict set cmdAttr ::eof \
        {killable Inf noCallFrame {}}
    dict set cmdAttr ::error \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::exit \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::fblocked \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::fconfigure \
        {killable 3 noCallFrame {}}
    dict set cmdAttr ::fcopy \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::fileevent \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::flush \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::format \
        {pure {} killable Inf noCallFrame {}}
    dict set cmdAttr ::gets \
        {writes 2}
    dict set cmdAttr ::glob \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::interp \
        [dict get $cmdAttr ::clock]
    dict set cmdAttr ::join \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::lrange \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::lrepeat \
................................................................................
    dict set cmdAttr ::lreverse \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::lsearch \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::lsort \
        [dict get $cmdAttr ::clock]
    dict set cmdAttr ::oo::InfoClass::call \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoClass::constructor \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoClass::definition \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoClass::destructor \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoClass::filters \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoClass::forward \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoClass::instances \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoClass::methods \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoClass::methodtype \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoClass::mixins \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoClass::subclasses \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoClass::superclasses \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoClass::variables \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoObject::call \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoObject::definition \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoObject::filters \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoObject::forward \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoObject::isa \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoObject::methods \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoObject::methodtype \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoObject::mixins \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoObject::variables \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::oo::InfoObject::vars \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::open \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::pid \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::platform::generic \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::platform::identify \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::platform::patterns \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::puts \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::pwd \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::read \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::regexp \
        [dict get $cmdAttr ::clock]
    dict set cmdAttr ::regsub \
        [dict get $cmdAttr ::clock]
    dict set cmdAttr ::scan \
        {writes -3}
    dict set cmdAttr ::seek \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::socket \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::split \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::binary::decode::base64 \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::binary::decode::hex \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::binary::decode::uuencode \
................................................................................
    dict set cmdAttr ::tcl::binary::format \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::binary::scan \
        [dict get $cmdAttr ::scan]
    dict set cmdAttr ::tcl::chan::blocked \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::chan::close \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::chan::copy \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::chan::create \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::chan::eof \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::chan::event \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::chan::flush \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::chan::gets \
        [dict get $cmdAttr ::gets]
    dict set cmdAttr ::tcl::chan::names \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::chan::pending \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::chan::pipe \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::chan::pop \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::chan::postevent \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::chan::push \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::chan::puts \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::chan::read \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::chan::seek \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::chan::tell \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::chan::truncate \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::clock::clicks \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::clock::microseconds \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::clock::milliseconds \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::clock::seconds \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::dict::keys \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::dict::values \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::file::atime \
        [dict get $cmdAttr ::fconfigure]
    dict set cmdAttr ::tcl::file::attributes \
        {killable 4 noCallFrame {}}
    dict set cmdAttr ::tcl::file::channels \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::file::copy \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::file::delete \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::file::dirname \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::file::executable \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::file::exists \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::file::extension \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::file::isdirectory \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::file::isfile \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::file::join \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::file::link \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::file::lstat \
        {writes 3}
    dict set cmdAttr ::tcl::file::mkdir \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::file::mtime \
        [dict get $cmdAttr ::fconfigure]
    dict set cmdAttr ::tcl::file::nativename \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::file::normalize \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::file::owned \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::file::pathtype \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::file::readable \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::file::readlink \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::file::rename \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::file::rootname \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::file::separator \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::file::size \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::file::split \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::file::stat \
        [dict get $cmdAttr ::tcl::file::lstat]
    dict set cmdAttr ::tcl::file::system \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::file::tail \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::file::tempfile \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::file::type \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::file::volumes \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::file::writable \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::info::args \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::info::body \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::info::cmdcount \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::info::commands \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::info::complete \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::info::default \
        [dict get $cmdAttr ::tcl::file::lstat]
    dict set cmdAttr ::tcl::info::errorstack \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::info::frame \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::info::functions \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::info::globals \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::info::hostname \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::info::library \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::info::loaded \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::info::locals \
        {killable Inf reads -1}
    dict set cmdAttr ::tcl::info::nameofexecutable \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::info::patchlevel \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::info::procs \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::info::script \
        {killable 2 noCallFrame {}}
    dict set cmdAttr ::tcl::info::sharedlibextension \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::info::tclversion \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::info::vars \
|







 







|



|







|

|



|



|

|







 







|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|









|

|

|







|

|







 







|

|

|



|

|



|

|

|



|



|

|

|



|

|

|

|

|





|



|

|





|

|



|

|









|

|

|

|



|

|







|





|





|

|

|

|

|

|

|





|

|

|

|





|







|







1
2
3
4
5
6
7
8
..
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
...
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
# CREATED BY parseBuiltinsTxt.tcl, DO NOT EDIT
#
#-----------------------------------------------------------------------------
#
#-----------------------------------------------------------------------------
#
# builtins.tcl.in --
#
................................................................................
    dict set cmdAttr ::after \
        {noCallFrame {}}
    dict set cmdAttr ::cd \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::clock \
        {special {}}
    dict set cmdAttr ::close \
        {nre {} noCallFrame {}}
    dict set cmdAttr ::encoding \
        [dict get $cmdAttr ::clock]
    dict set cmdAttr ::eof \
        {nre {} killable Inf noCallFrame {}}
    dict set cmdAttr ::error \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::exit \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::fblocked \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::fconfigure \
        {nre {} killable 3 noCallFrame {}}
    dict set cmdAttr ::fcopy \
        [dict get $cmdAttr ::close]
    dict set cmdAttr ::fileevent \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::flush \
        [dict get $cmdAttr ::close]
    dict set cmdAttr ::format \
        {pure {} killable Inf noCallFrame {}}
    dict set cmdAttr ::gets \
        {nre {} writes 2}
    dict set cmdAttr ::glob \
        {killable Inf noCallFrame {}}
    dict set cmdAttr ::interp \
        [dict get $cmdAttr ::clock]
    dict set cmdAttr ::join \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::lrange \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::lrepeat \
................................................................................
    dict set cmdAttr ::lreverse \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::lsearch \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::lsort \
        [dict get $cmdAttr ::clock]
    dict set cmdAttr ::oo::InfoClass::call \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoClass::constructor \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoClass::definition \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoClass::destructor \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoClass::filters \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoClass::forward \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoClass::instances \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoClass::methods \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoClass::methodtype \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoClass::mixins \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoClass::subclasses \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoClass::superclasses \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoClass::variables \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoObject::call \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoObject::definition \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoObject::filters \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoObject::forward \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoObject::isa \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoObject::methods \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoObject::methodtype \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoObject::mixins \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoObject::variables \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::oo::InfoObject::vars \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::open \
        [dict get $cmdAttr ::close]
    dict set cmdAttr ::pid \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::platform::generic \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::platform::identify \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::platform::patterns \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::puts \
        [dict get $cmdAttr ::close]
    dict set cmdAttr ::pwd \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::read \
        [dict get $cmdAttr ::close]
    dict set cmdAttr ::regexp \
        [dict get $cmdAttr ::clock]
    dict set cmdAttr ::regsub \
        [dict get $cmdAttr ::clock]
    dict set cmdAttr ::scan \
        {writes -3}
    dict set cmdAttr ::seek \
        [dict get $cmdAttr ::close]
    dict set cmdAttr ::socket \
        [dict get $cmdAttr ::close]
    dict set cmdAttr ::split \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::binary::decode::base64 \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::binary::decode::hex \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::binary::decode::uuencode \
................................................................................
    dict set cmdAttr ::tcl::binary::format \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::binary::scan \
        [dict get $cmdAttr ::scan]
    dict set cmdAttr ::tcl::chan::blocked \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::chan::close \
        [dict get $cmdAttr ::close]
    dict set cmdAttr ::tcl::chan::copy \
        [dict get $cmdAttr ::close]
    dict set cmdAttr ::tcl::chan::create \
        [dict get $cmdAttr ::close]
    dict set cmdAttr ::tcl::chan::eof \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::chan::event \
        [dict get $cmdAttr ::close]
    dict set cmdAttr ::tcl::chan::flush \
        [dict get $cmdAttr ::close]
    dict set cmdAttr ::tcl::chan::gets \
        [dict get $cmdAttr ::gets]
    dict set cmdAttr ::tcl::chan::names \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::chan::pending \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::chan::pipe \
        [dict get $cmdAttr ::close]
    dict set cmdAttr ::tcl::chan::pop \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::chan::postevent \
        [dict get $cmdAttr ::close]
    dict set cmdAttr ::tcl::chan::push \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::chan::puts \
        [dict get $cmdAttr ::close]
    dict set cmdAttr ::tcl::chan::read \
        [dict get $cmdAttr ::close]
    dict set cmdAttr ::tcl::chan::seek \
        [dict get $cmdAttr ::close]
    dict set cmdAttr ::tcl::chan::tell \
        [dict get $cmdAttr ::eof]
    dict set cmdAttr ::tcl::chan::truncate \
        [dict get $cmdAttr ::close]
    dict set cmdAttr ::tcl::clock::clicks \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::clock::microseconds \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::clock::milliseconds \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::clock::seconds \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::dict::keys \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::dict::values \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::file::atime \
        {killable 3 noCallFrame {}}
    dict set cmdAttr ::tcl::file::attributes \
        {killable 4 noCallFrame {}}
    dict set cmdAttr ::tcl::file::channels \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::file::copy \
        [dict get $cmdAttr ::close]
    dict set cmdAttr ::tcl::file::delete \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::file::dirname \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::file::executable \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::file::exists \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::file::extension \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::file::isdirectory \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::file::isfile \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::file::join \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::file::link \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::file::lstat \
        {writes 3}
    dict set cmdAttr ::tcl::file::mkdir \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::file::mtime \
        [dict get $cmdAttr ::tcl::file::atime]
    dict set cmdAttr ::tcl::file::nativename \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::file::normalize \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::file::owned \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::file::pathtype \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::file::readable \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::file::readlink \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::file::rename \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::file::rootname \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::file::separator \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::file::size \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::file::split \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::file::stat \
        [dict get $cmdAttr ::tcl::file::lstat]
    dict set cmdAttr ::tcl::file::system \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::file::tail \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::file::tempfile \
        [dict get $cmdAttr ::after]
    dict set cmdAttr ::tcl::file::type \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::file::volumes \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::file::writable \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::info::args \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::info::body \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::info::cmdcount \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::info::commands \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::info::complete \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::info::default \
        [dict get $cmdAttr ::tcl::file::lstat]
    dict set cmdAttr ::tcl::info::errorstack \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::info::frame \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::info::functions \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::info::globals \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::info::hostname \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::info::library \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::info::loaded \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::info::locals \
        {killable Inf reads -1}
    dict set cmdAttr ::tcl::info::nameofexecutable \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::info::patchlevel \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::info::procs \
        [dict get $cmdAttr ::glob]
    dict set cmdAttr ::tcl::info::script \
        {killable 2 noCallFrame {}}
    dict set cmdAttr ::tcl::info::sharedlibextension \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::info::tclversion \
        [dict get $cmdAttr ::format]
    dict set cmdAttr ::tcl::info::vars \

Changes to quadcode/builtins.txt.

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
...
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#GLOBAL NAMESPACE

#name                                   idem    kill    nre     reads   writes  notes

after                                   0       0       0
cd                                      0       0       0
clock                                   SPECIAL                                 <4>
close                                   0       0       0
encoding                                SPECIAL                                 <4>

eof                                     0       1       0
error                                   0       0       0
exit                                    0       0       0
fblocked                                0       1       0
fconfigure                              0       objc<=3 0
fcopy                                   0       0       0

fileevent                               0       0       0
flush                                   0       0       0
format                                  1       1       0
gets                                    0       0       0               objv[2]
glob                                    0       1       0
interp                                  SPECIAL                                 <?>

join                                    1       1       0
lrange                                  1       1       0
lrepeat                                 1       1       0
lreplace                                1       1       0
lreverse                                1       1       0
lsearch                                 1       1       0
lsort                                   SPECIAL                                 <1>

open                                    0       0       0
pid                                     1       1       0
puts                                    0       0       0
pwd                                     0       1       0
read                                    0       0       0

regexp                                  SPECIAL                                 <2>
regsub                                  SPECIAL                                 <3>
scan                                    0       0       0               objv[3+]
seek                                    0       0       0
socket                                  0       0       0

split                                   1       1       0
tell                                    0       1       0

#<1> lsort needs the callframe if -command is used, and needs whatever
#    variable access that the command needs. It's unkillable if the
#    command is unkillable. Without -command (the common case!) it doesn't
#    touch the callframe. Even most of the -commands will wind up being
#    killable and not need the callframe, but it's probably best to
#    ignore the case initially and simply announce that [lsort
................................................................................
tcl::binary::encode::*                  1       1       0
tcl::binary::format                     1       1       0
tcl::binary::scan                       0       0       0               objv[3+]

#THE [chan] ENSEMBLE

# name                                  idem    kill    nre     reads   writes  notes
tcl::chan::blocked                      0       1       0
tcl::chan::close                        0       0       0
tcl::chan::copy                         0       0       0
tcl::chan::create                       0       0       0
tcl::chan::eof                          0       1       0

tcl::chan::event                        0       0       0
tcl::chan::flush                        0       0       0
tcl::chan::gets                         0       0       0               objv[2]
tcl::chan::names                        0       1       0
tcl::chan::pending                      0       1       0

tcl::chan::pipe                         0       0       0
tcl::chan::pop                          0       0       0
tcl::chan::postevent                    0       0       0
tcl::chan::push                         0       0       0
tcl::chan::read                         0       0       0

tcl::chan::puts                         0       0       0
tcl::chan::seek                         0       0       0
tcl::chan::tell                         0       1       0
tcl::chan::truncate                     0       0       0

# THE [clock] ENSEMBLE

# name                                  idem    kill    nre     reads   writes  notes
tcl::clock::add                         0       1       0
tcl::clock::clicks                      0       1       0
tcl::clock::format                      0       1       0
................................................................................

#THE [file] ENSEMBLE

#name                                   idem    kill    nre     reads   writes  notes
tcl::file::atime                        0       objc<=3 0
tcl::file::attributes                   0       objc<=4 0
tcl::file::channels                     0       1       0
tcl::file::copy                         0       0       0
tcl::file::delete                       0       0       0

tcl::file::dirname                      1       1       0
tcl::file::executable                   0       1       0
tcl::file::exists                       0       1       0
tcl::file::extension                    1       1       0
tcl::file::isdirectory                  0       1

tcl::file::isfile                       0       1       0
tcl::file::join                         1       1       0
tcl::file::link                         0       0       0
tcl::file::lstat                        0       0       0               objv[3]  <5>
tcl::file::mkdir                        0       0       0








|


|


|
|
|


|

|











|

|

|




|
|


|







 







|
|
|
|
|

|
|
|



|

|

|

|
|
|
|







 







|






|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
...
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#GLOBAL NAMESPACE

#name                                   idem    kill    nre     reads   writes  notes

after                                   0       0       0
cd                                      0       0       0
clock                                   SPECIAL                                 <4>
close                                   0       0       1
encoding                                SPECIAL                                 <4>

eof                                     0       1       1
error                                   0       0       0
exit                                    0       0       0
fblocked                                0       1       1
fconfigure                              0       objc<=3 1
fcopy                                   0       0       1

fileevent                               0       0       0
flush                                   0       0       1
format                                  1       1       0
gets                                    0       0       1               objv[2]
glob                                    0       1       0
interp                                  SPECIAL                                 <?>

join                                    1       1       0
lrange                                  1       1       0
lrepeat                                 1       1       0
lreplace                                1       1       0
lreverse                                1       1       0
lsearch                                 1       1       0
lsort                                   SPECIAL                                 <1>

open                                    0       0       1
pid                                     1       1       0
puts                                    0       0       1
pwd                                     0       1       0
read                                    0       0       1

regexp                                  SPECIAL                                 <2>
regsub                                  SPECIAL                                 <3>
scan                                    0       0       0               objv[3+]
seek                                    0       0       1
socket                                  0       0       1

split                                   1       1       0
tell                                    0       1       1

#<1> lsort needs the callframe if -command is used, and needs whatever
#    variable access that the command needs. It's unkillable if the
#    command is unkillable. Without -command (the common case!) it doesn't
#    touch the callframe. Even most of the -commands will wind up being
#    killable and not need the callframe, but it's probably best to
#    ignore the case initially and simply announce that [lsort
................................................................................
tcl::binary::encode::*                  1       1       0
tcl::binary::format                     1       1       0
tcl::binary::scan                       0       0       0               objv[3+]

#THE [chan] ENSEMBLE

# name                                  idem    kill    nre     reads   writes  notes
tcl::chan::blocked                      0       1       1
tcl::chan::close                        0       0       1
tcl::chan::copy                         0       0       1
tcl::chan::create                       0       0       1
tcl::chan::eof                          0       1       1

tcl::chan::event                        0       0       1
tcl::chan::flush                        0       0       1
tcl::chan::gets                         0       0       1               objv[2]
tcl::chan::names                        0       1       0
tcl::chan::pending                      0       1       0

tcl::chan::pipe                         0       0       1
tcl::chan::pop                          0       0       0
tcl::chan::postevent                    0       0       1
tcl::chan::push                         0       0       0
tcl::chan::read                         0       0       1

tcl::chan::puts                         0       0       1
tcl::chan::seek                         0       0       1
tcl::chan::tell                         0       1       1
tcl::chan::truncate                     0       0       1

# THE [clock] ENSEMBLE

# name                                  idem    kill    nre     reads   writes  notes
tcl::clock::add                         0       1       0
tcl::clock::clicks                      0       1       0
tcl::clock::format                      0       1       0
................................................................................

#THE [file] ENSEMBLE

#name                                   idem    kill    nre     reads   writes  notes
tcl::file::atime                        0       objc<=3 0
tcl::file::attributes                   0       objc<=4 0
tcl::file::channels                     0       1       0
tcl::file::copy                         0       0       1
tcl::file::delete                       0       0       0

tcl::file::dirname                      1       1       0
tcl::file::executable                   0       1       0
tcl::file::exists                       0       1       0
tcl::file::extension                    1       1       0
tcl::file::isdirectory                  0       1	0

tcl::file::isfile                       0       1       0
tcl::file::join                         1       1       0
tcl::file::link                         0       0       0
tcl::file::lstat                        0       0       0               objv[3]  <5>
tcl::file::mkdir                        0       0       0

Changes to quadcode/specializer.tcl.

156
157
158
159
160
161
162




163
164
165
166
167
168
169
...
233
234
235
236
237
238
239




240
241
242
243
244
245
246
...
623
624
625
626
627
628
629



630
631
632
633
634
635
636
#
# Side effects:
#	The procedure's name is resolve in the caller's scope to a fully
#	qualified name. The procedure is converted to quadcode and its
#	quadcode database is added to the 'database' dictionary.

oo::define quadcode::specializer method register {procName} {





    # Fully qualify the procedure names and resolve imports.
    set realProc [uplevel 1 [list namespace which $procName]]

    if {$realProc eq {}} {
	puts stderr "Skipping $procName because the compiler can't resolve\
                     its name."
................................................................................
# Results:
#	None.
#
# Side effects:
#	Procedure instance is added to 'requiredInstances'.

oo::define quadcode::specializer method require {procName argTypes} {





    # Resolve the procedure name and handle namespace imports
    set realProc [uplevel 1 [list namespace which $procName]]
    set origin [uplevel 1 [list namespace origin $realProc]]

    # Add the procedure instance to the set of requred instances.
    dict set requiredInstances $origin $argTypes {}
................................................................................
oo::define quadcode::specializer method nonCompiledNeedsNRE {q argTypes} {

    if {[lindex $q 3 0] ne "literal"} {
	return 1;		# Unknown command invocation is always NRE
    }
    set name [lindex $q 3 1]
    set instance [list $name $argTypes]



    if {[dict exists $cmdAttr $name]} {
	set attrs [dict get $cmdAttr $name]
	if {[dict exists $attrs special]} {
	    set method frameEffect_[string map {:: __} $name]
	    set attrs [my $method $q]
	}
	if {! [dict exists $attrs nre]} {







>
>
>
>







 







>
>
>
>







 







>
>
>







156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
...
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
...
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
#
# Side effects:
#	The procedure's name is resolve in the caller's scope to a fully
#	qualified name. The procedure is converted to quadcode and its
#	quadcode database is added to the 'database' dictionary.

oo::define quadcode::specializer method register {procName} {

    my debug-specializer {
	puts "REGISTER: procName"
    }

    # Fully qualify the procedure names and resolve imports.
    set realProc [uplevel 1 [list namespace which $procName]]

    if {$realProc eq {}} {
	puts stderr "Skipping $procName because the compiler can't resolve\
                     its name."
................................................................................
# Results:
#	None.
#
# Side effects:
#	Procedure instance is added to 'requiredInstances'.

oo::define quadcode::specializer method require {procName argTypes} {

    my debug-specializer {
	puts "REQUIRE: $procName ([lmap t $argTypes {nameOfType $t}])"
    }

    # Resolve the procedure name and handle namespace imports
    set realProc [uplevel 1 [list namespace which $procName]]
    set origin [uplevel 1 [list namespace origin $realProc]]

    # Add the procedure instance to the set of requred instances.
    dict set requiredInstances $origin $argTypes {}
................................................................................
oo::define quadcode::specializer method nonCompiledNeedsNRE {q argTypes} {

    if {[lindex $q 3 0] ne "literal"} {
	return 1;		# Unknown command invocation is always NRE
    }
    set name [lindex $q 3 1]
    set instance [list $name $argTypes]
    my debug-specializer {
	puts "Does $name ([lmap x $argTypes {nameOfType $x}]) need NRE?"
    }
    if {[dict exists $cmdAttr $name]} {
	set attrs [dict get $cmdAttr $name]
	if {[dict exists $attrs special]} {
	    set method frameEffect_[string map {:: __} $name]
	    set attrs [my $method $q]
	}
	if {! [dict exists $attrs nre]} {