Check-in [9dbaca7922]
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

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

Overview
Comment:Generate only one moveFromCallFrame per bytecode instruction
Timelines: family | ancestors | descendants | both | notworking | kbk-refactor-callframe
Files: files | file ages | folders
SHA3-256: 9dbaca79223dd60cd49a835b3c269958975f2d21b4419087659e59927385232e
User & Date: kbk 2019-01-05 22:48:50
Context
2019-01-08
04:17
Fix more trivial errors in 'translate' and missing cases in code gen check-in: fba0ec7241 user: kbk tags: notworking, kbk-refactor-callframe
2019-01-05
22:48
Generate only one moveFromCallFrame per bytecode instruction check-in: 9dbaca7922 user: kbk tags: notworking, kbk-refactor-callframe
2019-01-02
02:20
Oops, one extra callframe ref in 'callframe-error-quads' check-in: cdc4d10e86 user: kbk tags: notworking, kbk-refactor-callframe
Changes

Changes to codegen/build.tcl.

6246
6247
6248
6249
6250
6251
6252
















6253
6254
6255
6256
6257
6258
6259
    # Results:
    #	Returns an LLVM INT reference

    method returnCode(FAIL\040STRING) {src ecode name} {
	my dropReference(FAIL\040STRING) $src
	my packInt32 $ecode $name
    }

















    # Builder:returnOptions(FAIL,INT) --
    #
    #	Get the Tcl exception dictionary. Quadcode implementation
    #	('returnOptions').
    #
    # Parameters:






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







6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
    # Results:
    #	Returns an LLVM INT reference

    method returnCode(FAIL\040STRING) {src ecode name} {
	my dropReference(FAIL\040STRING) $src
	my packInt32 $ecode $name
    }

    # Builder:returnCode(FAIL ZEROONE) --
    #
    #	Pass the Tcl return code through to an LLVM value
    #
    # Parameters:
    #	src - The FAIL ZEROONE value that encodes the last interpreter action
    #	ecode - The INT32 value that holds the return code
    #	name (optional) - A name to give to the result value
    #
    # Results:
    #	Returns an LLVM INT reference

    method returnCode(FAIL\040ZEROONE) {src ecode name} {
	my packInt32 $ecode
    }

    # Builder:returnOptions(FAIL,INT) --
    #
    #	Get the Tcl exception dictionary. Quadcode implementation
    #	('returnOptions').
    #
    # Parameters:

Changes to quadcode/transformer.tcl.

589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
    while {$changed} {
	set changed 0
	my debug-tidy {
	    set debugLine {tidy:}
	}
	foreach pass {
	    copyprop
	    cleanupMoveFromCallFrame
	    cleanupMoveToCallFrame
	    cleanupCallFrameUse
	    cleanupNarrow
	    bbidom
	    bblevel
	    deadcond
	    deadjump
	    deadbb
	    deadvars






<
<
<







589
590
591
592
593
594
595



596
597
598
599
600
601
602
    while {$changed} {
	set changed 0
	my debug-tidy {
	    set debugLine {tidy:}
	}
	foreach pass {
	    copyprop



	    cleanupNarrow
	    bbidom
	    bblevel
	    deadcond
	    deadjump
	    deadbb
	    deadvars

Changes to quadcode/translate.tcl.

459
460
461
462
463
464
465

466
467
468
469
470
471
472
...
486
487
488
489
490
491
492

493
494
495
496
497
498
499
...
502
503
504
505
506
507
508

509
510
511
512
513
514
515
516
517

518
519
520
521
522
523
524
525
526
527

528
529
530
531
532
533
534
...
540
541
542
543
544
545
546

547
548
549
550
551

552
553
554
555
556
557
558
...
573
574
575
576
577
578
579

580
581
582
583
584
585
586
...
591
592
593
594
595
596
597

598
599
600
601
602
603
604
...
606
607
608
609
610
611
612

613
614
615
616
617
618
619
...
621
622
623
624
625
626
627

628
629
630
631
632
633
634
...
641
642
643
644
645
646
647

648
649
650
651
652
653
654
...
837
838
839
840
841
842
843
844

845
846
847
848
849
850
851
...
854
855
856
857
858
859
860

861
862
863
864
865
866
867
868
869
870
871
872

873
874
875
876
877
878
879
880
881
882
883
884

885
886
887
888
889
890
891
....
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065

1066

1067
1068
1069
1070
1071
1072
1073
1074

1075
1076
1077
1078
1079
1080
1081
....
1123
1124
1125
1126
1127
1128
1129

1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140

1141
1142
1143
1144
1145
1146
1147
....
1218
1219
1220
1221
1222
1223
1224

1225
1226
1227
1228
1229
1230
1231
....
1232
1233
1234
1235
1236
1237
1238

1239
1240
1241
1242
1243
1244
1245
....
1258
1259
1260
1261
1262
1263
1264

1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276

1277
1278
1279
1280
1281
1282
1283
....
1284
1285
1286
1287
1288
1289
1290

1291
1292
1293
1294
1295
1296
1297
....
1300
1301
1302
1303
1304
1305
1306

1307
1308
1309
1310
1311
1312
1313
....
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333

1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
....
1552
1553
1554
1555
1556
1557
1558


















1559
1560
1561
1562
1563
1564
1565
....
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592

1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
....
1631
1632
1633
1634
1635
1636
1637

1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720

1721
1722
1723
1724
1725
1726
1727
		    if {[llength $varGroup] == 1} {
			my quads copy $idx $res
		    } else {
			my quads mult $idx $res [list literal [llength $varGroup]]
		    }
		    foreach varIndex $varGroup {
			set var [my index-to-var $varIndex]

			my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
			    "can't set \"%s\": variable is array"
			my quads listIndex $var $list $idx
			my quads extractMaybe $var $var
			my quads add $idx $idx [list literal 1]
		    }
		}
................................................................................
		set collector [list temp [expr {$depth - [llength $assign] - 4}]]
		set value [list temp [incr depth -1]]
		my quads listAppend $collector $collector $value
		my quads extractMaybe $collector $collector
	    }
	    dictFirst {
		set var [my index-to-var [lindex $insn 1]]

		set dict [list temp [incr depth -1]]
		set value [list temp $depth]
		set key [list temp [incr depth]]
		set done [list temp [incr depth]]
		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my error-quads $pc dictIterStart $var $dict
................................................................................
		my quads dictIterDone $done $var
	    }
	    dictNext {
		set var [my index-to-var [lindex $insn 1]]
		set value [list temp $depth]
		set key [list temp [incr depth]]
		set done [list temp [incr depth]]

		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my quads dictIterNext $var $var
		my quads dictIterKey $key $var
		my quads dictIterValue $value $var
		my quads dictIterDone $done $var
	    }
	    dictUpdateStart {
		set var [my index-to-var [lindex $insn 1]]

		my generate-scalar-check $pc $var {TCL READ VARNAME} \
		    "can't read \"%s\": variable is array"
		set auxNum [string range [lindex $insn 2] 1 end]
		set aux [lindex [dict get $bytecode auxiliary] $auxNum]
		set mid [list temp opnd0]
		set val [list temp [incr depth -1]]
		set idx 0
		set toUpdate {}
		foreach v [dict get $aux variables] {
		    set r [my index-to-var $v]

		    my generate-scalar-check $pc $r {TCL WRITE VARNAME} \
			"can't set \"%s\": variable is array"
		    my error-quads $pc listIndex $mid $val [list literal $idx]
		    my error-quads $pc dictGetOrNexist $r $var $mid
		    lappend toUpdate [list literal [lindex $r 1]] $r
		    incr idx
		}
................................................................................
		set aux [lindex [dict get $bytecode auxiliary] $auxNum]
		set key [list temp opnd1]
		set isary [list temp opnd2]
		set mid [list temp opnd3]
		set updating [list temp opnd4]
		set val [list temp [incr depth -1]]
		set idx 0

		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't write \"%s\": variable is array"
		my quads copy $updating $var
		foreach v [dict get $aux variables] {
		    set r [my index-to-var $v]

		    my error-quads $pc listIndex $key $val [list literal $idx]
		    incr idx
		    # Convert an ARRAY into a NEXIST here; ARRAY is unreadable
		    # so treat as NEXIST...
		    my quads arrayExists $isary $r
		    set n [llength $quads]
		    my quads jumpFalse [list pc [expr {$n + 3}]] $isary
................................................................................
		my update-in-callframe [list literal [lindex $var 1]] Nothing
	    }
	    unsetArray {
		# TODO - This doesn't complain on unsetting a nonexistent
		#        element, it ignores '-nocomplain'
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 2]]

		my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \
		    "can't unset \"%s(%s)\": variable isn't array"
		my quads initArrayIfNotExists $ary $ary
		my quads arrayUnset $ary $ary $idx
		my update-in-callframe [list literal [lindex $ary 1]] $ary
	    }
	    dictDone {
................................................................................
		my error-quads $pc dictSize $r $r
		# The result will be discarded
	    }
	    incrScalar1Imm {
		set result [list temp $depth]
		set var [my index-to-var [lindex $insn 1]]
		set delta [lindex $insn 2]

		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my quads initIfNotExists $var $var {literal 0}
	        my quads copy $result [list literal $delta]
		my generate-arith-domain-check $pc incr $var $result
		my quads purify {temp opd0} $var
		my quads purify {temp opd1} $result
................................................................................
		my update-in-callframe [list literal [lindex $var 1]] $var
		my quads copy $result $var
	    }
	    incrScalar1 {
		set result [list temp $depth]
		set val [list temp [incr depth -1]]
		set var [my index-to-var [lindex $insn 1]]

		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my quads initIfNotExists $var $var {literal 0}
		my generate-arith-domain-check $pc incr $var $val
		my quads purify {temp opd0} $var
		my quads purify {temp opd1} $val
		my quads add $var {temp opd0} {temp opd1}
................................................................................
		my quads copy $result $var
	    }
	    incrArray1Imm {
		set tmp [list temp $depth]
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 1]]
		set delta [list literal [lindex $insn 2]]

		my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \
		    "can't read \"%s(%s)\": variable isn't array"
		my quads initArrayIfNotExists $ary $ary
		my quads copy $tmp $delta
		set res $idx
		set inval {temp opd0}
		my quads arrayGet $inval $ary $idx
................................................................................
		my update-in-callframe [list literal [lindex $ary 1]] $ary
		my quads copy $res $inval
	    }
	    incrArray1 {
		set delta [list temp [incr depth -1]]
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 1]]

		my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \
		    "can't read \"%s(%s)\": variable isn't array"
		my quads initArrayIfNotExists $ary $ary
		set res $idx
		set inval {temp opd0}
		my quads arrayGet $inval $ary $idx
		my quads initIfNotExists $inval $inval {literal 0}
................................................................................
		set var [my index-to-var [lindex $insn 2]]
		set val [list temp [incr depth -1]]
		set q {}
		for {set i 0} {$i < $idxNum} {incr i} {
		    # NOTE: Reversed
		    lappend q [list temp [incr depth -1]]
		}
		set r [list temp $depth]

		my generate-scalar-check $pc $var {TCL READ VARNAME} \
		    "can't read \"%s\": variable is array"
		my quads initIfNotExists $var $var {literal {}}
		my error-quads $pc dictSet $r $var $val {*}[lreverse $q]
		my quads copy $var $r
		my update-in-callframe [list literal [lindex $var 1]] $var
	    }
................................................................................
		set var [my index-to-var [lindex $insn 2]]
		set q {}
		for {set i 0} {$i < $idxNum} {incr i} {
		    # NOTE: Reversed
		    lappend q [list temp [incr depth -1]]
		}
		set r [list temp $depth]

		my generate-scalar-check $pc $var {TCL READ VARNAME} \
		    "can't read \"%s\": variable is array"
		my quads initIfNotExists $var $var {literal {}}
		my error-quads $pc dictUnset $r $var {*}[lreverse $q]
		my quads copy $var $r
		my update-in-callframe [list literal [lindex $var 1]] $var
	    }
	    dictAppend - dictLappend {
		set var [my index-to-var [lindex $insn 1]]
		set val [list temp [incr depth -1]]
		set key [list temp [incr depth -1]]
		set res [list temp $depth]

		my generate-scalar-check $pc $var {TCL READ VARNAME} \
		    "can't read \"%s\": variable is array"
		my quads initIfNotExists $var $var {literal {}}
		my error-quads $pc [lindex $insn 0] $res $var $key $val
		my quads copy $var $res
		my update-in-callframe [list literal [lindex $var 1]] $var
	    }
	    dictIncrImm {
		set delta [list literal [lindex $insn 1]]
		set var [my index-to-var [lindex $insn 2]]
		set key [list temp [incr depth -1]]
		set res [list temp $depth]

		my generate-scalar-check $pc $var {TCL READ VARNAME} \
		    "can't read \"%s\": variable is array"
		my quads initIfNotExists $var $var {literal {}}
		my error-quads $pc dictIncr $res $var $key $delta
		my quads copy $var $res
		my update-in-callframe [list literal [lindex $var 1]] $var
	    }
................................................................................
		    set to_pc [expr {$pc + $offset}]
		    my generate-jump $to_pc true $test
		}
	    }
	    existScalar {
		set result [list temp $depth]
		set var [my index-to-var [lindex $insn 1]]
		my quads moveFromCallFrame \
		    $var $cf [list literal [lindex $var 1]]
		my quads exists $result $var
	    }
	    existArray {
		set tmp [list temp $depth]
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 1]]
		set result $idx
		my quads moveFromCallFrame \
		    $var $cf [list literal [lindex $var 1]]
		my quads initArrayIfNotExists $tmp $ary
		my quads arrayElementExists $result $tmp $idx
	    }

	    loadScalar1 -
	    loadScalar4 {	# Load a variable
		set result [list temp $depth]
		set var [my index-to-var [lindex $insn 1]]

		my generate-existence-check $pc $var

		my generate-scalar-check $pc $var {TCL READ VARNAME} \
		    "can't read \"%s\": variable is array"
		my quads copy $result $var
	    }
	    loadArray1 -
	    loadArray4 {	# Load from an array
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 1]]

		my generate-existence-check $pc $ary
		my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \
		    "can't read \"%s(%s)\": variable isn't array"
		set res $idx
		my quads arrayGet $res $ary $idx
		set name [lindex $ary 1](...)
		# FIXME: error variable name
................................................................................
		# For now, startCommand does nothing
		# lappend quads startCommand
	    }
	    storeScalar1 -
	    storeScalar4 {	# Store a variable
		incr depth -1
		set var [my index-to-var [lindex $insn 1]]

		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my quads copy $var [list temp $depth]
		my update-in-callframe [list literal [lindex $var 1]] $var
	    }
	    storeArray1 -
	    storeArray4 {	# Store into an array
		set val [list temp [incr depth -1]]
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 1]]
		set res $idx

		my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \
		    "can't set \"%s(%s)\": variable isn't array"
		my quads initArrayIfNotExists $ary $ary
		my quads arraySet $ary $ary $idx $val
		my quads copy $res $val
		my update-in-callframe [list literal [lindex $ary 1]] $ary
	    }
................................................................................
		set v0 [list temp [incr depth -1]]
		set r $v0
		my error-quads $pc [lindex $insn 0] $r $v0
	    }
	    appendScalar1 - appendScalar4 {
		set val [list temp [incr depth -1]]
		set var [my index-to-var [lindex $insn 1]]

		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my quads initIfNotExists $var $var {literal {}}
		set result [list temp $depth]
		my quads strcat $var $var $val
		my quads copy $result $var
		my update-in-callframe [list literal [lindex $var 1]] $var
................................................................................
	    }
	    appendArray1 - appendArray4 {
		set val [list temp [incr depth -1]]
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 1]]
		set res [list temp $depth]
		set inval {temp opd0}

		my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \
		    "can't set \"%s(%s)\": variable isn't array"
		my quads initArrayIfNotExists $ary $ary
		my quads arrayGet $inval $ary $idx
		my quads initIfNotExists $inval $inval {literal {}}
		my quads strcat $inval $inval $val
		my quads arraySet $ary $ary $idx $inval
................................................................................
		}
		my quads $op $result {*}[lreverse $strcatvals]
	    }
	    lappendScalar1 - lappendScalar4 {
		set val [list temp [incr depth -1]]
		set var [my index-to-var [lindex $insn 1]]
		set res [list temp $depth]

		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my quads initIfNotExists $var $var {literal {}}
		# TODO: Typecheck: need list in $var
		my error-quads $pc listAppend $res $var $val
		my quads copy $var $res
		my update-in-callframe [list literal [lindex $var 1]] $var
	    }
	    lappendList {
		set listval [list temp [incr depth -1]]
		set var [my index-to-var [lindex $insn 1]]
		set res [list temp $depth]

		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my quads initIfNotExists $var $var {literal {}}
		# TODO: Typecheck: need lists in $var and $listval
		my error-quads $pc listConcat $res $var $listval
		my quads copy $var $res
		my update-in-callframe [list literal [lindex $var 1]] $var
................................................................................
	    }
	    lappendArray1 - lappendArray4 {
		set val [list temp [incr depth -1]]
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 1]]
		set res [list temp $depth]
		set inval {temp opd0}

		my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \
		    "can't set \"%s(%s)\": variable isn't array"
		my quads initArrayIfNotExists $var $var
		my quads arrayGet $inval $ary $idx
		my quads initIfNotExists $inval $inval {literal {}}
		my error-quads $pc listAppend $inval $inval $val
		my quads arraySet $ary $ary $idx $inval
................................................................................
	    }
	    lappendListArray {
		set listval [list temp [incr depth -1]]
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 1]]
		set res [list temp $depth]
		set inval {temp opd0}

		my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \
		    "can't set \"%s(%s)\": variable isn't array"
		my quads initArrayIfNotExists $ary $ary
		my quads arrayGet $inval $ary $idx
		my quads initIfNotExists $inval $inval {literal {}}
		# TODO: Typecheck: need lists in $inval and $listval
		my error-quads $pc listConcat $inval $inval $listval
................................................................................
		set list1 [list temp [incr depth -1]]
		set res [list temp $depth]
		# TODO: Typecheck: need lists in $list1 and $list2
		my error-quads $pc listConcat $res $list1 $list2
	    }
	    arrayExistsImm {
		set ary [my index-to-var [lindex $insn 1]]
		my quads moveFromCallFrame \
		    $ary $cf [list literal [lindex $ary 1]]
		set res [list temp $depth]
		my quads arrayExists $res $ary
	    }
	    arrayMakeImm {
		set ary [my index-to-var [lindex $insn 1]]

		my generate-array-check $pc $ary {} {TCL WRITE ARRAY} \
		    "can't array set \"%s\": variable isn't array"
		my quads initArrayIfNotExists $ary $ary
		my update-in-callframe [list literal [lindex $var 1]] $var
	    }
	    arrayExistsStk {
		set ary [list temp [incr depth -1]]
		set res [list temp $depth]
		my error-quads $pc directIsArray $res $cf $ary
	    }
	    arrayMakeStk {
................................................................................
    if {[llength $args] == 2} {
	lassign $args type var
	my quads jump[string totitle $type] $target $var
    } else {
	my quads jump $target
    }
}



















# generate-existence-check --
#
#	Generates a check to make sure that a variable exists, and
#	appends it to the list of quadcodes being built. Do not call from
#	anywhere but bytecode-to-quads!
#
................................................................................
    if {$varname eq ""} {
	set varname [lreplace $var 0 0 literal]
    }
    if {[lindex $varname 0] ne "literal"} {
	error "Not implemented! generate-existence-check on non-constant name"
    }
    set varname [lindex $varname 1]

    set where [llength $quads]
    set newtemp [list temp @exists]


    my quads moveFromCallFrame \
	$var {temp @callframe} [list literal [lindex $var 1]]
    my quads exists $newtemp $var					;# 0
    my quads jumpTrue [list pc [expr {$where + 5}]] $newtemp		;# 1
    set msg [list literal "can't read \"$varname\": no such variable"]
    set optionsDict \
	[list literal [list -errorcode [list TCL LOOKUP VARNAME $varname]]]
    my quads initException {temp @exception} $msg $optionsDict \
	{literal 1} {literal 0}						;# 2
................................................................................
#	requested error if it is incorrect.

oo::define quadcode::transformer method generate-array-check {pc var idx error msg} {

    set varname [lindex $var 1]
    ;				# Name of the variable being checked


    set ok [list pc [expr {[llength $quads] + 11}]]
    ;				# Quadcode address to jump to on success
    set fail [my exception-target $pc catch]
    ;				# Bytecode address to jump to on failure
    
    # If this is a real variable and not a temporary (e.g. a dict iterator),
    # make sure that it's pulled from the callframe. Load elimination will
    # delete this instruction if possible.
    if {[lindex $var 0] eq "var"} {
	# 0
	my quads moveFromCallFrame $var {temp @callframe} \
	    [list literal [lindex $var 1]]
    }
    # 1
    my quads exists {temp @exists} $var
    # 2
    my quads jumpFalse $ok {temp @exists}
    # 3
    my quads arrayExists {temp @exists} $var
    # 4
    my quads jumpTrue $ok {temp @exists}
    # 5
    if {$idx ne {}} {
	my quads invoke {temp @callframe} {temp @callframe} \
	    {literal ::format} [list literal $msg] \
	    [list literal $varname] $idx
    } else {
	my quads invoke {temp @callframe} {temp @callframe} \
	    {literal ::format} [list literal $msg] \
	    [list literal $varname]
    }
    # 6
    my quads retrieveResult {temp @msg} {temp @callframe}
    # 7
    my quads extractCallFrame {temp @callframe} {temp @callframe}
    # 8
    my quads extractMaybe {temp @msg} {temp @msg}
    # 9
    my quads initException {temp @exception} {temp @msg} \
	[list literal [list -errorcode $error]] \
	{literal 1} {literal 0}
    # 10
    my quads extractFail {temp @exception} {temp @exception}
    # 11
    my generate-jump $fail
    # 12

    # The narrowing pass will insert any necessary 'extract...' instructions
}

oo::define quadcode::transformer method generate-scalar-check {pc var error msg} {
    
    set varname [lindex $var 1]
    ;				# Name of the variable being checked
    set msg [list literal [format $msg $varname]]
    ;				# Preformatted message to return on error
    
    set ok [list pc [expr {[llength $quads] + 5}]]
    ;				# Quadcode address to jump to on success
    set fail [my exception-target $pc catch]
    ;				# Bytecode address to jump to on failure
    
    # If this is a real variable and not a temporary (e.g. a dict iterator),
    # make sure that it's pulled from the callframe. Load elimination will
    # delete this instruction if possible.
    if {[lindex $var 0] eq "var"} {
	# 0
	my quads moveFromCallFrame $var {temp @callframe} \
	    [list literal [lindex $var 1]]
    }
    # 1
    my quads arrayExists {temp @exists} $var
    # 2
    my quads jumpFalse $ok {temp @exists}
    # 3
    my quads initException {temp @exception} $msg \
	[list literal [list -errorcode $error]] \
	{literal 1} {literal 0}
    # 4
    my quads extractFail {temp @exception} {temp @exception}
    # 5
    my generate-jump $fail
    # 6


    # The narrowing pass will insert any necessary 'extract...' instructions
}

# generate-arith-domain-check --
#
#	Generates a check to make sure that a value is NUMERIC or INT






>







 







>







 







>









>










>







 







>





>







 







>







 







>







 







>







 







>







 







>







 







|
>







 







>












>












>







 







|
<







|
<








>

>


|





>







 







>











>







 







>







 







>







 







>












>







 







>







 







>







 







|
<





>



|







 







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







 







<
<

>

<
<







 







>




<
<
<
<
<
|
<
<
<
<

|

|

|

|









|

|

|

|



|

|

|










<





<
<
<
<
|
<
<
<
<

|

|



|

|

|
>







459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
...
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
...
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
...
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
...
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
...
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
...
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
...
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
...
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
...
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
...
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
....
1056
1057
1058
1059
1060
1061
1062
1063

1064
1065
1066
1067
1068
1069
1070
1071

1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
....
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
....
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
1264
1265
1266
....
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
....
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
....
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
....
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
....
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
....
1626
1627
1628
1629
1630
1631
1632


1633
1634
1635


1636
1637
1638
1639
1640
1641
1642
....
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682





1683




1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725

1726
1727
1728
1729
1730




1731




1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
		    if {[llength $varGroup] == 1} {
			my quads copy $idx $res
		    } else {
			my quads mult $idx $res [list literal [llength $varGroup]]
		    }
		    foreach varIndex $varGroup {
			set var [my index-to-var $varIndex]
			my generate-move-from-callframe $var
			my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
			    "can't set \"%s\": variable is array"
			my quads listIndex $var $list $idx
			my quads extractMaybe $var $var
			my quads add $idx $idx [list literal 1]
		    }
		}
................................................................................
		set collector [list temp [expr {$depth - [llength $assign] - 4}]]
		set value [list temp [incr depth -1]]
		my quads listAppend $collector $collector $value
		my quads extractMaybe $collector $collector
	    }
	    dictFirst {
		set var [my index-to-var [lindex $insn 1]]
		my generate-move-from-callframe $var
		set dict [list temp [incr depth -1]]
		set value [list temp $depth]
		set key [list temp [incr depth]]
		set done [list temp [incr depth]]
		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my error-quads $pc dictIterStart $var $dict
................................................................................
		my quads dictIterDone $done $var
	    }
	    dictNext {
		set var [my index-to-var [lindex $insn 1]]
		set value [list temp $depth]
		set key [list temp [incr depth]]
		set done [list temp [incr depth]]
		my generate-move-from-callframe $var
		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my quads dictIterNext $var $var
		my quads dictIterKey $key $var
		my quads dictIterValue $value $var
		my quads dictIterDone $done $var
	    }
	    dictUpdateStart {
		set var [my index-to-var [lindex $insn 1]]
		my generate-move-from-callframe $var
		my generate-scalar-check $pc $var {TCL READ VARNAME} \
		    "can't read \"%s\": variable is array"
		set auxNum [string range [lindex $insn 2] 1 end]
		set aux [lindex [dict get $bytecode auxiliary] $auxNum]
		set mid [list temp opnd0]
		set val [list temp [incr depth -1]]
		set idx 0
		set toUpdate {}
		foreach v [dict get $aux variables] {
		    set r [my index-to-var $v]
		    my generate-move-from-callframe $r
		    my generate-scalar-check $pc $r {TCL WRITE VARNAME} \
			"can't set \"%s\": variable is array"
		    my error-quads $pc listIndex $mid $val [list literal $idx]
		    my error-quads $pc dictGetOrNexist $r $var $mid
		    lappend toUpdate [list literal [lindex $r 1]] $r
		    incr idx
		}
................................................................................
		set aux [lindex [dict get $bytecode auxiliary] $auxNum]
		set key [list temp opnd1]
		set isary [list temp opnd2]
		set mid [list temp opnd3]
		set updating [list temp opnd4]
		set val [list temp [incr depth -1]]
		set idx 0
		my generate-move-from-callframe $var
		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't write \"%s\": variable is array"
		my quads copy $updating $var
		foreach v [dict get $aux variables] {
		    set r [my index-to-var $v]
		    my generate-move-from-callframe $r
		    my error-quads $pc listIndex $key $val [list literal $idx]
		    incr idx
		    # Convert an ARRAY into a NEXIST here; ARRAY is unreadable
		    # so treat as NEXIST...
		    my quads arrayExists $isary $r
		    set n [llength $quads]
		    my quads jumpFalse [list pc [expr {$n + 3}]] $isary
................................................................................
		my update-in-callframe [list literal [lindex $var 1]] Nothing
	    }
	    unsetArray {
		# TODO - This doesn't complain on unsetting a nonexistent
		#        element, it ignores '-nocomplain'
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 2]]
		my generate-move-from-callframe $ary
		my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \
		    "can't unset \"%s(%s)\": variable isn't array"
		my quads initArrayIfNotExists $ary $ary
		my quads arrayUnset $ary $ary $idx
		my update-in-callframe [list literal [lindex $ary 1]] $ary
	    }
	    dictDone {
................................................................................
		my error-quads $pc dictSize $r $r
		# The result will be discarded
	    }
	    incrScalar1Imm {
		set result [list temp $depth]
		set var [my index-to-var [lindex $insn 1]]
		set delta [lindex $insn 2]
		my generate-move-from-callframe $var
		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my quads initIfNotExists $var $var {literal 0}
	        my quads copy $result [list literal $delta]
		my generate-arith-domain-check $pc incr $var $result
		my quads purify {temp opd0} $var
		my quads purify {temp opd1} $result
................................................................................
		my update-in-callframe [list literal [lindex $var 1]] $var
		my quads copy $result $var
	    }
	    incrScalar1 {
		set result [list temp $depth]
		set val [list temp [incr depth -1]]
		set var [my index-to-var [lindex $insn 1]]
		my generate-move-from-callframe $var
		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my quads initIfNotExists $var $var {literal 0}
		my generate-arith-domain-check $pc incr $var $val
		my quads purify {temp opd0} $var
		my quads purify {temp opd1} $val
		my quads add $var {temp opd0} {temp opd1}
................................................................................
		my quads copy $result $var
	    }
	    incrArray1Imm {
		set tmp [list temp $depth]
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 1]]
		set delta [list literal [lindex $insn 2]]
		my generate-move-from-callframe $ary
		my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \
		    "can't read \"%s(%s)\": variable isn't array"
		my quads initArrayIfNotExists $ary $ary
		my quads copy $tmp $delta
		set res $idx
		set inval {temp opd0}
		my quads arrayGet $inval $ary $idx
................................................................................
		my update-in-callframe [list literal [lindex $ary 1]] $ary
		my quads copy $res $inval
	    }
	    incrArray1 {
		set delta [list temp [incr depth -1]]
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 1]]
		my generate-move-from-callframe $ary
		my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \
		    "can't read \"%s(%s)\": variable isn't array"
		my quads initArrayIfNotExists $ary $ary
		set res $idx
		set inval {temp opd0}
		my quads arrayGet $inval $ary $idx
		my quads initIfNotExists $inval $inval {literal 0}
................................................................................
		set var [my index-to-var [lindex $insn 2]]
		set val [list temp [incr depth -1]]
		set q {}
		for {set i 0} {$i < $idxNum} {incr i} {
		    # NOTE: Reversed
		    lappend q [list temp [incr depth -1]]
		}
		set r [list temp $depth]	
		my generate-move-from-callframe $var
		my generate-scalar-check $pc $var {TCL READ VARNAME} \
		    "can't read \"%s\": variable is array"
		my quads initIfNotExists $var $var {literal {}}
		my error-quads $pc dictSet $r $var $val {*}[lreverse $q]
		my quads copy $var $r
		my update-in-callframe [list literal [lindex $var 1]] $var
	    }
................................................................................
		set var [my index-to-var [lindex $insn 2]]
		set q {}
		for {set i 0} {$i < $idxNum} {incr i} {
		    # NOTE: Reversed
		    lappend q [list temp [incr depth -1]]
		}
		set r [list temp $depth]
		my generate-move-from-callframe $var
		my generate-scalar-check $pc $var {TCL READ VARNAME} \
		    "can't read \"%s\": variable is array"
		my quads initIfNotExists $var $var {literal {}}
		my error-quads $pc dictUnset $r $var {*}[lreverse $q]
		my quads copy $var $r
		my update-in-callframe [list literal [lindex $var 1]] $var
	    }
	    dictAppend - dictLappend {
		set var [my index-to-var [lindex $insn 1]]
		set val [list temp [incr depth -1]]
		set key [list temp [incr depth -1]]
		set res [list temp $depth]
		my generate-move-from-callframe $var
		my generate-scalar-check $pc $var {TCL READ VARNAME} \
		    "can't read \"%s\": variable is array"
		my quads initIfNotExists $var $var {literal {}}
		my error-quads $pc [lindex $insn 0] $res $var $key $val
		my quads copy $var $res
		my update-in-callframe [list literal [lindex $var 1]] $var
	    }
	    dictIncrImm {
		set delta [list literal [lindex $insn 1]]
		set var [my index-to-var [lindex $insn 2]]
		set key [list temp [incr depth -1]]
		set res [list temp $depth]
		my generate-move-from-callframe $var
		my generate-scalar-check $pc $var {TCL READ VARNAME} \
		    "can't read \"%s\": variable is array"
		my quads initIfNotExists $var $var {literal {}}
		my error-quads $pc dictIncr $res $var $key $delta
		my quads copy $var $res
		my update-in-callframe [list literal [lindex $var 1]] $var
	    }
................................................................................
		    set to_pc [expr {$pc + $offset}]
		    my generate-jump $to_pc true $test
		}
	    }
	    existScalar {
		set result [list temp $depth]
		set var [my index-to-var [lindex $insn 1]]
		my generate-move-from-callframe $var

		my quads exists $result $var
	    }
	    existArray {
		set tmp [list temp $depth]
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 1]]
		set result $idx
		my generate-move-from-callframe $ary

		my quads initArrayIfNotExists $tmp $ary
		my quads arrayElementExists $result $tmp $idx
	    }

	    loadScalar1 -
	    loadScalar4 {	# Load a variable
		set result [list temp $depth]
		set var [my index-to-var [lindex $insn 1]]
		my generate-move-from-callframe $var
		my generate-existence-check $pc $var
		my quads copy $result $var
		my generate-scalar-check $pc $var {TCL READ VARNAME} \
		    "can't read \"%s\": variable is array"
		#my quads copy $result $var
	    }
	    loadArray1 -
	    loadArray4 {	# Load from an array
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 1]]
		my generate-move-from-callframe $ary
		my generate-existence-check $pc $ary
		my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \
		    "can't read \"%s(%s)\": variable isn't array"
		set res $idx
		my quads arrayGet $res $ary $idx
		set name [lindex $ary 1](...)
		# FIXME: error variable name
................................................................................
		# For now, startCommand does nothing
		# lappend quads startCommand
	    }
	    storeScalar1 -
	    storeScalar4 {	# Store a variable
		incr depth -1
		set var [my index-to-var [lindex $insn 1]]
		my generate-move-from-callframe $var
		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my quads copy $var [list temp $depth]
		my update-in-callframe [list literal [lindex $var 1]] $var
	    }
	    storeArray1 -
	    storeArray4 {	# Store into an array
		set val [list temp [incr depth -1]]
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 1]]
		set res $idx
		my generate-move-from-callframe $ary
		my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \
		    "can't set \"%s(%s)\": variable isn't array"
		my quads initArrayIfNotExists $ary $ary
		my quads arraySet $ary $ary $idx $val
		my quads copy $res $val
		my update-in-callframe [list literal [lindex $ary 1]] $ary
	    }
................................................................................
		set v0 [list temp [incr depth -1]]
		set r $v0
		my error-quads $pc [lindex $insn 0] $r $v0
	    }
	    appendScalar1 - appendScalar4 {
		set val [list temp [incr depth -1]]
		set var [my index-to-var [lindex $insn 1]]
		my generate-move-from-callframe $var
		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my quads initIfNotExists $var $var {literal {}}
		set result [list temp $depth]
		my quads strcat $var $var $val
		my quads copy $result $var
		my update-in-callframe [list literal [lindex $var 1]] $var
................................................................................
	    }
	    appendArray1 - appendArray4 {
		set val [list temp [incr depth -1]]
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 1]]
		set res [list temp $depth]
		set inval {temp opd0}
		my generate-move-from-callframe $ary
		my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \
		    "can't set \"%s(%s)\": variable isn't array"
		my quads initArrayIfNotExists $ary $ary
		my quads arrayGet $inval $ary $idx
		my quads initIfNotExists $inval $inval {literal {}}
		my quads strcat $inval $inval $val
		my quads arraySet $ary $ary $idx $inval
................................................................................
		}
		my quads $op $result {*}[lreverse $strcatvals]
	    }
	    lappendScalar1 - lappendScalar4 {
		set val [list temp [incr depth -1]]
		set var [my index-to-var [lindex $insn 1]]
		set res [list temp $depth]
		my generate-move-from-callframe $var
		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my quads initIfNotExists $var $var {literal {}}
		# TODO: Typecheck: need list in $var
		my error-quads $pc listAppend $res $var $val
		my quads copy $var $res
		my update-in-callframe [list literal [lindex $var 1]] $var
	    }
	    lappendList {
		set listval [list temp [incr depth -1]]
		set var [my index-to-var [lindex $insn 1]]
		set res [list temp $depth]
		my generate-move-from-callframe $var
		my generate-scalar-check $pc $var {TCL WRITE VARNAME} \
		    "can't set \"%s\": variable is array"
		my quads initIfNotExists $var $var {literal {}}
		# TODO: Typecheck: need lists in $var and $listval
		my error-quads $pc listConcat $res $var $listval
		my quads copy $var $res
		my update-in-callframe [list literal [lindex $var 1]] $var
................................................................................
	    }
	    lappendArray1 - lappendArray4 {
		set val [list temp [incr depth -1]]
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 1]]
		set res [list temp $depth]
		set inval {temp opd0}
		my generate-move-from-callframe $ary
		my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \
		    "can't set \"%s(%s)\": variable isn't array"
		my quads initArrayIfNotExists $var $var
		my quads arrayGet $inval $ary $idx
		my quads initIfNotExists $inval $inval {literal {}}
		my error-quads $pc listAppend $inval $inval $val
		my quads arraySet $ary $ary $idx $inval
................................................................................
	    }
	    lappendListArray {
		set listval [list temp [incr depth -1]]
		set idx [list temp [incr depth -1]]
		set ary [my index-to-var [lindex $insn 1]]
		set res [list temp $depth]
		set inval {temp opd0}
		my generate-move-from-callframe $ary
		my generate-array-check $pc $ary $idx {TCL LOOKUP VARNAME} \
		    "can't set \"%s(%s)\": variable isn't array"
		my quads initArrayIfNotExists $ary $ary
		my quads arrayGet $inval $ary $idx
		my quads initIfNotExists $inval $inval {literal {}}
		# TODO: Typecheck: need lists in $inval and $listval
		my error-quads $pc listConcat $inval $inval $listval
................................................................................
		set list1 [list temp [incr depth -1]]
		set res [list temp $depth]
		# TODO: Typecheck: need lists in $list1 and $list2
		my error-quads $pc listConcat $res $list1 $list2
	    }
	    arrayExistsImm {
		set ary [my index-to-var [lindex $insn 1]]
		my generate-move-from-callframe $ary

		set res [list temp $depth]
		my quads arrayExists $res $ary
	    }
	    arrayMakeImm {
		set ary [my index-to-var [lindex $insn 1]]
		my generate-move-from-callframe $ary
		my generate-array-check $pc $ary {} {TCL WRITE ARRAY} \
		    "can't array set \"%s\": variable isn't array"
		my quads initArrayIfNotExists $ary $ary
		my update-in-callframe [list literal [lindex $ary 1]] $ary
	    }
	    arrayExistsStk {
		set ary [list temp [incr depth -1]]
		set res [list temp $depth]
		my error-quads $pc directIsArray $res $cf $ary
	    }
	    arrayMakeStk {
................................................................................
    if {[llength $args] == 2} {
	lassign $args type var
	my quads jump[string totitle $type] $target $var
    } else {
	my quads jump $target
    }
}

# generate-move-from-callframe --
#
#	Generates a 'moveFromCallFrame' instruction for a given variable.
#
# Parameters:
#	var - Variable to load
#
# Results:
#	None.
#
# Side effects:
#	Emits the quad

oo::define quadcode::transformer method generate-move-from-callframe {var} {
    my quads moveFromCallFrame $var {temp @callframe} \
	[list literal [lindex $var 1]]
}

# generate-existence-check --
#
#	Generates a check to make sure that a variable exists, and
#	appends it to the list of quadcodes being built. Do not call from
#	anywhere but bytecode-to-quads!
#
................................................................................
    if {$varname eq ""} {
	set varname [lreplace $var 0 0 literal]
    }
    if {[lindex $varname 0] ne "literal"} {
	error "Not implemented! generate-existence-check on non-constant name"
    }
    set varname [lindex $varname 1]


    set newtemp [list temp @exists]
    set where [llength $quads]



    my quads exists $newtemp $var					;# 0
    my quads jumpTrue [list pc [expr {$where + 5}]] $newtemp		;# 1
    set msg [list literal "can't read \"$varname\": no such variable"]
    set optionsDict \
	[list literal [list -errorcode [list TCL LOOKUP VARNAME $varname]]]
    my quads initException {temp @exception} $msg $optionsDict \
	{literal 1} {literal 0}						;# 2
................................................................................
#	requested error if it is incorrect.

oo::define quadcode::transformer method generate-array-check {pc var idx error msg} {

    set varname [lindex $var 1]
    ;				# Name of the variable being checked

    
    set ok [list pc [expr {[llength $quads] + 11}]]
    ;				# Quadcode address to jump to on success
    set fail [my exception-target $pc catch]
    ;				# Bytecode address to jump to on failure





    # 0




    my quads exists {temp @exists} $var
    # 1
    my quads jumpFalse $ok {temp @exists}
    # 2
    my quads arrayExists {temp @exists} $var
    # 3
    my quads jumpTrue $ok {temp @exists}
    # 4
    if {$idx ne {}} {
	my quads invoke {temp @callframe} {temp @callframe} \
	    {literal ::format} [list literal $msg] \
	    [list literal $varname] $idx
    } else {
	my quads invoke {temp @callframe} {temp @callframe} \
	    {literal ::format} [list literal $msg] \
	    [list literal $varname]
    }
    # 5
    my quads retrieveResult {temp @msg} {temp @callframe}
    # 6
    my quads extractCallFrame {temp @callframe} {temp @callframe}
    # 7
    my quads extractMaybe {temp @msg} {temp @msg}
    # 8
    my quads initException {temp @exception} {temp @msg} \
	[list literal [list -errorcode $error]] \
	{literal 1} {literal 0}
    # 9
    my quads extractFail {temp @exception} {temp @exception}
    # 10
    my generate-jump $fail
    # 11

    # The narrowing pass will insert any necessary 'extract...' instructions
}

oo::define quadcode::transformer method generate-scalar-check {pc var error msg} {
    
    set varname [lindex $var 1]
    ;				# Name of the variable being checked
    set msg [list literal [format $msg $varname]]
    ;				# Preformatted message to return on error

    set ok [list pc [expr {[llength $quads] + 5}]]
    ;				# Quadcode address to jump to on success
    set fail [my exception-target $pc catch]
    ;				# Bytecode address to jump to on failure
    




    # 0




    my quads arrayExists {temp @exists} $var
    # 1
    my quads jumpFalse $ok {temp @exists}
    # 2
    my quads initException {temp @exception} $msg \
	[list literal [list -errorcode $error]] \
	{literal 1} {literal 0}
    # 3
    my quads extractFail {temp @exception} {temp @exception}
    # 4
    my generate-jump $fail
    # 5
    # next-instruction

    # The narrowing pass will insert any necessary 'extract...' instructions
}

# generate-arith-domain-check --
#
#	Generates a check to make sure that a value is NUMERIC or INT