OpenFPGA/libs/EXTERNAL/tcl8.6.12/tests/assemble.test

3359 lines
62 KiB
Plaintext
Raw Normal View History

2022-06-07 11:15:20 -05:00
# assemble.test --
#
# Test suite for the 'tcl::unsupported::assemble' command
#
# Copyright (c) 2010 by Ozgur Dogan Ugurlu.
# Copyright (c) 2010 by Kevin B. Kenny.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#-----------------------------------------------------------------------------
# Commands covered: assemble
if {"::tcltest" ni [namespace children]} {
package require tcltest 2.5
namespace import -force ::tcltest::*
}
namespace eval tcl::unsupported {namespace export assemble}
namespace import tcl::unsupported::assemble
# Procedure to make code that fills the literal and local variable tables, to
# force instructions to spill to four bytes.
proc fillTables {} {
set s {}
set sep {}
for {set i 0} {$i < 256} {incr i} {
append s $sep [list set v$i literal$i]
set sep \n
}
return $s
}
testConstraint memory [llength [info commands memory]]
if {[testConstraint memory]} {
proc getbytes {} {
set lines [split [memory info] \n]
return [lindex $lines 3 3]
}
proc leaktest {script {iterations 3}} {
set end [getbytes]
for {set i 0} {$i < $iterations} {incr i} {
uplevel 1 $script
set tmp $end
set end [getbytes]
}
return [expr {$end - $tmp}]
}
}
# assemble-1 - TclNRAssembleObjCmd
test assemble-1.1 {wrong # args, direct eval} {
-body {
eval [list assemble]
}
-returnCodes error
-result {wrong # args*}
-match glob
}
test assemble-1.2 {wrong # args, direct eval} {
-body {
eval [list assemble too many]
}
-returnCodes error
-result {wrong # args*}
-match glob
}
test assemble-1.3 {error reporting, direct eval} {
-body {
list [catch {
eval [list assemble {
# bad opcode
rubbish
}]
} result] $result $errorInfo
}
-match glob
-result {1 {bad instruction "rubbish":*} {bad instruction "rubbish":*
while executing
"rubbish"
("assemble" body, line 3)*}}
-cleanup {unset result}
}
test assemble-1.4 {simple direct eval} {
-body {
eval [list assemble {push {this is a test}}]
}
-result {this is a test}
}
# assemble-2 - CompileAssembleObj
test assemble-2.1 {bytecode reuse, direct eval} {
-body {
set x {push "this is a test"}
list [eval [list assemble $x]] \
[eval [list assemble $x]]
}
-result {{this is a test} {this is a test}}
}
test assemble-2.2 {bytecode discard, direct eval} {
-body {
set x {load value}
proc p1 {x} {
set value value1
assemble $x
}
proc p2 {x} {
set a b
set value value2
assemble $x
}
list [p1 $x] [p2 $x]
}
-result {value1 value2}
-cleanup {
unset x
rename p1 {}
rename p2 {}
}
}
test assemble-2.3 {null script, direct eval} {
-body {
set x {}
assemble $x
}
-result {}
-cleanup {unset x}
}
# assemble-3 - TclCompileAssembleCmd
test assemble-3.1 {wrong # args, compiled path} {
-body {
proc x {} {
assemble
}
x
}
-returnCodes error
-match glob
-result {wrong # args:*}
}
test assemble-3.2 {wrong # args, compiled path} {
-body {
proc x {} {
assemble too many
}
x
}
-returnCodes error
-match glob
-result {wrong # args:*}
-cleanup {
rename x {}
}
}
# assemble-4 - TclAssembleCode mainline
test assemble-4.1 {syntax error} {
-body {
proc x {} {
assemble {
{}extra
}
}
list [catch x result] $result $::errorInfo
}
-cleanup {
rename x {}
unset result
}
-match glob
-result {1 {extra characters after close-brace} {extra characters after close-brace
while executing
"{}e"
("assemble" body, line 2)*}}
}
test assemble-4.2 {null command} {
-body {
proc x {} {
assemble {
push hello; pop;;push goodbye
}
}
x
}
-result goodbye
-cleanup {
rename x {}
}
}
# assemble-5 - GetNextOperand off-nominal cases
test assemble-5.1 {unsupported expansion} {
-body {
proc x {y} {
assemble {
{*}$y
}
}
list [catch {x {push hello}} result] $result $::errorCode
}
-result {1 {assembly code may not contain substitutions} {TCL ASSEM NOSUBST}}
-cleanup {
rename x {}
unset result
}
}
test assemble-5.2 {unsupported substitution} {
-body {
proc x {y} {
assemble {
$y
}
}
list [catch {x {nop}} result] $result $::errorCode
}
-cleanup {
rename x {}
unset result
}
-result {1 {assembly code may not contain substitutions} {TCL ASSEM NOSUBST}}
}
test assemble-5.3 {unsupported substitution} {
-body {
proc x {} {
assemble {
[x]
}
}
list [catch {x} result] $result $::errorCode
}
-result {1 {assembly code may not contain substitutions} {TCL ASSEM NOSUBST}}
}
test assemble-5.4 {backslash substitution} {
-body {
proc x {} {
assemble {
p\x75sh\
hello\ world
}
}
x
}
-cleanup {
rename x {}
}
-result {hello world}
}
# assemble-6 - ASSEM_PUSH
test assemble-6.1 {push, wrong # args} {
-body {
assemble push
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-6.2 {push, wrong # args} {
-body {
assemble {push too many}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-6.3 {push} {
-body {
eval [list assemble {push hello}]
}
-result hello
}
test assemble-6.4 {push4} {
-body {
proc x {} "
[fillTables]
assemble {push hello}
"
x
}
-cleanup {
rename x {}
}
-result hello
}
# assemble-7 - ASSEM_1BYTE
test assemble-7.1 {add, wrong # args} {
-body {
assemble {add excess}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-7.2 {add} {
-body {
assemble {
push 2
push 2
add
}
}
-result {4}
}
test assemble-7.3 {appendArrayStk} {
-body {
set a(b) {hello, }
assemble {
push a
push b
push world
appendArrayStk
}
set a(b)
}
-result {hello, world}
-cleanup {unset a}
}
test assemble-7.4 {appendStk} {
-body {
set a {hello, }
assemble {
push a
push world
appendStk
}
set a
}
-result {hello, world}
-cleanup {unset a}
}
test assemble-7.5 {bitwise ops} {
-body {
list \
[assemble {push 0b1100; push 0b1010; bitand}] \
[assemble {push 0b1100; bitnot}] \
[assemble {push 0b1100; push 0b1010; bitor}] \
[assemble {push 0b1100; push 0b1010; bitxor}]
}
-result {8 -13 14 6}
}
test assemble-7.6 {div} {
-body {
assemble {push 999999; push 7; div}
}
-result 142857
}
test assemble-7.7 {dup} {
-body {
assemble {
push 1; dup; dup; add; dup; add; dup; add; add
}
}
-result 9
}
test assemble-7.8 {eq} {
-body {
list \
[assemble {push able; push baker; eq}] \
[assemble {push able; push able; eq}]
}
-result {0 1}
}
test assemble-7.9 {evalStk} {
-body {
assemble {
push {concat test 7.3}
evalStk
}
}
-result {test 7.3}
}
test assemble-7.9a {evalStk, syntax} {
-body {
assemble {
push {{}bad}
evalStk
}
}
-returnCodes error
-result {extra characters after close-brace}
}
test assemble-7.9b {evalStk, backtrace} {
-body {
proc y {z} {
error testing
}
proc x {} {
assemble {
push {
# test error in evalStk
y asd
}
evalStk
}
}
list [catch x result] $result $errorInfo
}
-result {1 testing {testing
while executing
"error testing"
(procedure "y" line 2)
invoked from within
"y asd"*}}
-match glob
-cleanup {
rename y {}
rename x {}
}
}
test assemble-7.10 {existArrayStk} {
-body {
proc x {name key} {
set a(b) c
assemble {
load name; load key; existArrayStk
}
}
list [x a a] [x a b] [x b a] [x b b]
}
-result {0 1 0 0}
-cleanup {rename x {}}
}
test assemble-7.11 {existStk} {
-body {
proc x {name} {
set a b
assemble {
load name; existStk
}
}
list [x a] [x b]
}
-result {1 0}
-cleanup {rename x {}}
}
test assemble-7.12 {expon} {
-body {
assemble {push 3; push 4; expon}
}
-result 81
}
test assemble-7.13 {exprStk} {
-body {
assemble {
push {acos(-1)}
exprStk
}
}
-result 3.141592653589793
}
test assemble-7.13a {exprStk, syntax} {
-body {
assemble {
push {2+}
exprStk
}
}
-returnCodes error
-result {missing operand at _@_
in expression "2+_@_"}
}
test assemble-7.13b {exprStk, backtrace} {
-body {
proc y {z} {
error testing
}
proc x {} {
assemble {
push {[y asd]}
exprStk
}
}
list [catch x result] $result $errorInfo
}
-result {1 testing {testing
while executing
"error testing"
(procedure "y" line 2)
invoked from within
"y asd"*}}
-match glob
-cleanup {
rename y {}
rename x {}
}
}
test assemble-7.14 {ge gt le lt} {
-body {
proc x {a b} {
list [assemble {load a; load b; ge}] \
[assemble {load a; load b; gt}] \
[assemble {load a; load b; le}] \
[assemble {load a; load b; lt}]
}
list [x 0 0] [x 0 1] [x 1 0]
}
-result {{1 0 1 0} {0 0 1 1} {1 1 0 0}}
-cleanup {rename x {}}
}
test assemble-7.15 {incrArrayStk} {
-body {
proc x {} {
set a(b) 5
assemble {
push a; push b; push 7; incrArrayStk
}
}
x
}
-result 12
-cleanup {rename x {}}
}
test assemble-7.16 {incrStk} {
-body {
proc x {} {
set a 5
assemble {
push a; push 7; incrStk
}
}
x
}
-result 12
-cleanup {rename x {}}
}
test assemble-7.17 {land/lor} {
-body {
proc x {a b} {
list \
[assemble {load a; load b; land}] \
[assemble {load a; load b; lor}]
}
list [x 0 0] [x 0 23] [x 35 0] [x 47 59]
}
-result {{0 0} {0 1} {0 1} {1 1}}
-cleanup {rename x {}}
}
test assemble-7.18 {lappendArrayStk} {
-body {
proc x {} {
set able(baker) charlie
assemble {
push able
push baker
push dog
lappendArrayStk
}
}
x
}
-result {charlie dog}
-cleanup {rename x {}}
}
test assemble-7.19 {lappendStk} {
-body {
proc x {} {
set able baker
assemble {
push able
push charlie
lappendStk
}
}
x
}
-result {baker charlie}
-cleanup {rename x {}}
}
test assemble-7.20 {listIndex} {
-body {
assemble {
push {a b c d}
push 2
listIndex
}
}
-result c
}
test assemble-7.21 {listLength} {
-body {
assemble {
push {a b c d}
listLength
}
}
-result 4
}
test assemble-7.22 {loadArrayStk} {
-body {
proc x {} {
set able(baker) charlie
assemble {
push able
push baker
loadArrayStk
}
}
x
}
-result charlie
-cleanup {rename x {}}
}
test assemble-7.23 {loadStk} {
-body {
proc x {} {
set able baker
assemble {
push able
loadStk
}
}
x
}
-result baker
-cleanup {rename x {}}
}
test assemble-7.24 {lsetList} {
-body {
proc x {} {
set l {{a b} {c d} {e f} {g h}}
assemble {
push {2 1}; push i; load l; lsetList
}
}
x
}
-result {{a b} {c d} {e i} {g h}}
}
test assemble-7.25 {lshift} {
-body {
assemble {push 16; push 4; lshift}
}
-result 256
}
test assemble-7.26 {mod} {
-body {
assemble {push 123456; push 1000; mod}
}
-result 456
}
test assemble-7.27 {mult} {
-body {
assemble {push 12345679; push 9; mult}
}
-result 111111111
}
test assemble-7.28 {neq} {
-body {
list \
[assemble {push able; push baker; neq}] \
[assemble {push able; push able; neq}]
}
-result {1 0}
}
test assemble-7.29 {not} {
-body {
list \
[assemble {push 17; not}] \
[assemble {push 0; not}]
}
-result {0 1}
}
test assemble-7.30 {pop} {
-body {
assemble {push this; pop; push that}
}
-result that
}
test assemble-7.31 {rshift} {
-body {
assemble {push 257; push 4; rshift}
}
-result 16
}
test assemble-7.32 {storeArrayStk} {
-body {
proc x {} {
assemble {
push able; push baker; push charlie; storeArrayStk
}
array get able
}
x
}
-result {baker charlie}
-cleanup {rename x {}}
}
test assemble-7.33 {storeStk} {
-body {
proc x {} {
assemble {
push able; push baker; storeStk
}
set able
}
x
}
-result {baker}
-cleanup {rename x {}}
}
test assemble-7,34 {strcmp} {
-body {
proc x {a b} {
assemble {
load a; load b; strcmp
}
}
list [x able baker] [x baker able] [x baker baker]
}
-result {-1 1 0}
-cleanup {rename x {}}
}
test assemble-7.35 {streq/strneq} {
-body {
proc x {a b} {
list \
[assemble {load a; load b; streq}] \
[assemble {load a; load b; strneq}]
}
list [x able able] [x able baker]
}
-result {{1 0} {0 1}}
-cleanup {rename x {}}
}
test assemble-7.36 {strindex} {
-body {
assemble {push testing; push 4; strindex}
}
-result i
}
test assemble-7.37 {strlen} {
-body {
assemble {push testing; strlen}
}
-result 7
}
test assemble-7.38 {sub} {
-body {
assemble {push 42; push 17; sub}
}
-result 25
}
test assemble-7.39 {tryCvtToNumeric} {
-body {
assemble {
push 42; tryCvtToNumeric
}
}
-result 42
}
# assemble-7.40 absent
test assemble-7.41 {uminus} {
-body {
assemble {
push 42; uminus
}
}
-result -42
}
test assemble-7.42 {uplus} {
-body {
assemble {
push 42; uplus
}
}
-result 42
}
test assemble-7.43 {uplus} {
-body {
assemble {
push NaN; uplus
}
}
-returnCodes error
-result {can't use non-numeric floating-point value as operand of "+"}
}
test assemble-7.43.1 {tryCvtToNumeric} {
-body {
assemble {
push NaN; tryCvtToNumeric
}
}
-returnCodes error
-result {domain error: argument not in valid range}
}
test assemble-7.44 {listIn} {
-body {
assemble {
push b; push {a b c}; listIn
}
}
-result 1
}
test assemble-7.45 {listNotIn} {
-body {
assemble {
push d; push {a b c}; listNotIn
}
}
-result 1
}
test assemble-7.46 {nop} {
-body {
assemble { push x; nop; nop; nop}
}
-result x
}
# assemble-8 ASSEM_LVT and FindLocalVar
test assemble-8.1 {load, wrong # args} {
-body {
assemble load
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-8.2 {load, wrong # args} {
-body {
assemble {load too many}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-8.3 {nonlocal var} {
-body {
list [catch {assemble {load ::env}} result] $result $errorCode
}
-result {1 {variable "::env" is not local} {TCL ASSEM NONLOCAL ::env}}
-cleanup {unset result}
}
test assemble-8.4 {bad context} {
-body {
set x 1
list [catch {assemble {load x}} result] $result $errorCode
}
-result {1 {cannot use this instruction to create a variable in a non-proc context} {TCL ASSEM LVT}}
-cleanup {unset result}
}
test assemble-8.5 {bad context} {
-body {
namespace eval assem {
set x 1
list [catch {assemble {load x}} result opts] $result [dict get $opts -errorcode]
}
}
-result {1 {cannot use this instruction to create a variable in a non-proc context} {TCL ASSEM LVT}}
-cleanup {namespace delete assem}
}
test assemble-8.6 {load1} {
-body {
proc x {a} {
assemble {
load a
}
}
x able
}
-result able
-cleanup {rename x {}}
}
test assemble-8.7 {load4} {
-body {
proc x {a} "
[fillTables]
set b \$a
assemble {load b}
"
x able
}
-result able
-cleanup {rename x {}}
}
test assemble-8.8 {loadArray1} {
-body {
proc x {} {
set able(baker) charlie
assemble {
push baker
loadArray able
}
}
x
}
-result charlie
-cleanup {rename x {}}
}
test assemble-8.9 {loadArray4} {
-body "
proc x {} {
[fillTables]
set able(baker) charlie
assemble {
push baker
loadArray able
}
}
x
"
-result charlie
-cleanup {rename x {}}
}
test assemble-8.10 {append1} {
-body {
proc x {} {
set y {hello, }
assemble {
push world; append y
}
}
x
}
-result {hello, world}
-cleanup {rename x {}}
}
test assemble-8.11 {append4} {
-body {
proc x {} "
[fillTables]
set y {hello, }
assemble {
push world; append y
}
"
x
}
-result {hello, world}
-cleanup {rename x {}}
}
test assemble-8.12 {appendArray1} {
-body {
proc x {} {
set y(z) {hello, }
assemble {
push z; push world; appendArray y
}
}
x
}
-result {hello, world}
-cleanup {rename x {}}
}
test assemble-8.13 {appendArray4} {
-body {
proc x {} "
[fillTables]
set y(z) {hello, }
assemble {
push z; push world; appendArray y
}
"
x
}
-result {hello, world}
-cleanup {rename x {}}
}
test assemble-8.14 {lappend1} {
-body {
proc x {} {
set y {hello,}
assemble {
push world; lappend y
}
}
x
}
-result {hello, world}
-cleanup {rename x {}}
}
test assemble-8.15 {lappend4} {
-body {
proc x {} "
[fillTables]
set y {hello,}
assemble {
push world; lappend y
}
"
x
}
-result {hello, world}
-cleanup {rename x {}}
}
test assemble-8.16 {lappendArray1} {
-body {
proc x {} {
set y(z) {hello,}
assemble {
push z; push world; lappendArray y
}
}
x
}
-result {hello, world}
-cleanup {rename x {}}
}
test assemble-8.17 {lappendArray4} {
-body {
proc x {} "
[fillTables]
set y(z) {hello,}
assemble {
push z; push world; lappendArray y
}
"
x
}
-result {hello, world}
-cleanup {rename x {}}
}
test assemble-8.18 {store1} {
-body {
proc x {} {
assemble {
push test; store y
}
set y
}
x
}
-result {test}
-cleanup {rename x {}}
}
test assemble-8.19 {store4} {
-body {
proc x {} "
[fillTables]
assemble {
push test; store y
}
set y
"
x
}
-result test
-cleanup {rename x {}}
}
test assemble-8.20 {storeArray1} {
-body {
proc x {} {
assemble {
push z; push test; storeArray y
}
set y(z)
}
x
}
-result test
-cleanup {rename x {}}
}
test assemble-8.21 {storeArray4} {
-body {
proc x {} "
[fillTables]
assemble {
push z; push test; storeArray y
}
"
x
}
-result test
-cleanup {rename x {}}
}
# assemble-9 - ASSEM_CONCAT1, GetIntegerOperand, CheckOneByte
test assemble-9.1 {wrong # args} {
-body {assemble concat}
-result {wrong # args*}
-match glob
-returnCodes error
}
test assemble-9.2 {wrong # args} {
-body {assemble {concat too many}}
-result {wrong # args*}
-match glob
-returnCodes error
}
test assemble-9.3 {not a number} {
-body {assemble {concat rubbish}}
-result {expected integer but got "rubbish"}
-returnCodes error
}
test assemble-9.4 {too small} {
-body {assemble {concat -1}}
-result {operand does not fit in one byte}
-returnCodes error
}
test assemble-9.5 {too small} {
-body {assemble {concat 256}}
-result {operand does not fit in one byte}
-returnCodes error
}
test assemble-9.6 {concat} {
-body {
assemble {push h; push e; push l; push l; push o; concat 5}
}
-result hello
}
test assemble-9.7 {concat} {
-body {
list [catch {assemble {concat 0}} result] $result $::errorCode
}
-result {1 {operand must be positive} {TCL ASSEM POSITIVE}}
-cleanup {unset result}
}
# assemble-10 -- eval and expr
test assemble-10.1 {eval - wrong # args} {
-body {
assemble {eval}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-10.2 {eval - wrong # args} {
-body {
assemble {eval too many}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-10.3 {eval} {
-body {
proc x {} {
assemble {
push 3
store n
pop
eval {expr {3*$n + 1}}
push 1
add
}
}
x
}
-result 11
-cleanup {rename x {}}
}
test assemble-10.4 {expr} {
-body {
proc x {} {
assemble {
push 3
store n
pop
expr {3*$n + 1}
push 1
add
}
}
x
}
-result 11
-cleanup {rename x {}}
}
test assemble-10.5 {eval and expr - nonsimple} {
-body {
proc x {} {
assemble {
eval "s\x65t n 3"
pop
expr "\x33*\$n + 1"
push 1
add
}
}
x
}
-result 11
-cleanup {
rename x {}
}
}
test assemble-10.6 {eval - noncompilable} {
-body {
list [catch {assemble {eval $x}} result] $result $::errorCode
}
-result {1 {assembly code may not contain substitutions} {TCL ASSEM NOSUBST}}
}
test assemble-10.7 {expr - noncompilable} {
-body {
list [catch {assemble {expr $x}} result] $result $::errorCode
}
-result {1 {assembly code may not contain substitutions} {TCL ASSEM NOSUBST}}
}
# assemble-11 - ASSEM_LVT4 (exist, existArray, dictAppend, dictLappend,
# nsupvar, variable, upvar)
test assemble-11.1 {exist - wrong # args} {
-body {
assemble {exist}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-11.2 {exist - wrong # args} {
-body {
assemble {exist too many}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-11.3 {nonlocal var} {
-body {
list [catch {assemble {exist ::env}} result] $result $errorCode
}
-result {1 {variable "::env" is not local} {TCL ASSEM NONLOCAL ::env}}
-cleanup {unset result}
}
test assemble-11.4 {exist} {
-body {
proc x {} {
set y z
list [assemble {exist y}] \
[assemble {exist z}]
}
x
}
-result {1 0}
-cleanup {rename x {}}
}
test assemble-11.5 {existArray} {
-body {
proc x {} {
set a(b) c
list [assemble {push b; existArray a}] \
[assemble {push c; existArray a}] \
[assemble {push a; existArray b}]
}
x
}
-result {1 0 0}
-cleanup {rename x {}}
}
test assemble-11.6 {dictAppend} {
-body {
proc x {} {
set dict {a 1 b 2 c 3}
assemble {push b; push 22; dictAppend dict}
}
x
}
-result {a 1 b 222 c 3}
-cleanup {rename x {}}
}
test assemble-11.7 {dictLappend} {
-body {
proc x {} {
set dict {a 1 b 2 c 3}
assemble {push b; push 2; dictLappend dict}
}
x
}
-result {a 1 b {2 2} c 3}
-cleanup {rename x {}}
}
test assemble-11.8 {upvar} {
-body {
proc x {v} {
assemble {push 1; load v; upvar w; pop; load w}
}
proc y {} {
set z 123
x z
}
y
}
-result 123
-cleanup {rename x {}; rename y {}}
}
test assemble-11.9 {nsupvar} {
-body {
namespace eval q { variable v 123 }
proc x {} {
assemble {push q; push v; nsupvar y; pop; load y}
}
x
}
-result 123
-cleanup {namespace delete q; rename x {}}
}
test assemble-11.10 {variable} {
-body {
namespace eval q { namespace eval r {variable v 123}}
proc x {} {
assemble {push q::r::v; variable y; load y}
}
x
}
-result 123
-cleanup {namespace delete q; rename x {}}
}
# assemble-12 - ASSEM_LVT1 (incr and incrArray)
test assemble-12.1 {incr - wrong # args} {
-body {
assemble {incr}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-12.2 {incr - wrong # args} {
-body {
assemble {incr too many}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-12.3 {incr nonlocal var} {
-body {
list [catch {assemble {incr ::env}} result] $result $errorCode
}
-result {1 {variable "::env" is not local} {TCL ASSEM NONLOCAL ::env}}
-cleanup {unset result}
}
test assemble-12.4 {incr} {
-body {
proc x {} {
set y 5
assemble {push 3; incr y}
}
x
}
-result 8
-cleanup {rename x {}}
}
test assemble-12.5 {incrArray} {
-body {
proc x {} {
set a(b) 5
assemble {push b; push 3; incrArray a}
}
x
}
-result 8
-cleanup {rename x {}}
}
test assemble-12.6 {incr, stupid stack restriction} {
-body {
proc x {} "
[fillTables]
set y 5
assemble {push 3; incr y}
"
list [catch {x} result] $result $errorCode
}
-result {1 {operand does not fit in one byte} {TCL ASSEM 1BYTE}}
-cleanup {unset result; rename x {}}
}
# assemble-13 -- ASSEM_LVT1_SINT1 - incrImm and incrArrayImm
test assemble-13.1 {incrImm - wrong # args} {
-body {
assemble {incrImm x}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-13.2 {incrImm - wrong # args} {
-body {
assemble {incrImm too many args}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-13.3 {incrImm nonlocal var} {
-body {
list [catch {assemble {incrImm ::env 2}} result] $result $errorCode
}
-result {1 {variable "::env" is not local} {TCL ASSEM NONLOCAL ::env}}
-cleanup {unset result}
}
test assemble-13.4 {incrImm not a number} {
-body {
proc x {} {
assemble {incrImm x rubbish}
}
x
}
-returnCodes error
-result {expected integer but got "rubbish"}
-cleanup {rename x {}}
}
test assemble-13.5 {incrImm too big} {
-body {
proc x {} {
assemble {incrImm x 0x80}
}
list [catch x result] $result $::errorCode
}
-result {1 {operand does not fit in one byte} {TCL ASSEM 1BYTE}}
-cleanup {rename x {}; unset result}
}
test assemble-13.6 {incrImm too small} {
-body {
proc x {} {
assemble {incrImm x -0x81}
}
list [catch x result] $result $::errorCode
}
-result {1 {operand does not fit in one byte} {TCL ASSEM 1BYTE}}
-cleanup {rename x {}; unset result}
}
test assemble-13.7 {incrImm} {
-body {
proc x {} {
set y 1
list [assemble {incrImm y -0x80}] [assemble {incrImm y 0x7f}]
}
x
}
-result {-127 0}
-cleanup {rename x {}}
}
test assemble-13.8 {incrArrayImm} {
-body {
proc x {} {
set a(b) 5
assemble {push b; incrArrayImm a 3}
}
x
}
-result 8
-cleanup {rename x {}}
}
test assemble-13.9 {incrImm, stupid stack restriction} {
-body {
proc x {} "
[fillTables]
set y 5
assemble {incrImm y 3}
"
list [catch {x} result] $result $errorCode
}
-result {1 {operand does not fit in one byte} {TCL ASSEM 1BYTE}}
-cleanup {unset result; rename x {}}
}
# assemble-14 -- ASSEM_SINT1 (incrArrayStkImm and incrStkImm)
test assemble-14.1 {incrStkImm - wrong # args} {
-body {
assemble {incrStkImm}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-14.2 {incrStkImm - wrong # args} {
-body {
assemble {incrStkImm too many}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-14.3 {incrStkImm not a number} {
-body {
proc x {} {
assemble {incrStkImm rubbish}
}
x
}
-returnCodes error
-result {expected integer but got "rubbish"}
-cleanup {rename x {}}
}
test assemble-14.4 {incrStkImm too big} {
-body {
proc x {} {
assemble {incrStkImm 0x80}
}
list [catch x result] $result $::errorCode
}
-result {1 {operand does not fit in one byte} {TCL ASSEM 1BYTE}}
-cleanup {rename x {}; unset result}
}
test assemble-14.5 {incrStkImm too small} {
-body {
proc x {} {
assemble {incrStkImm -0x81}
}
list [catch x result] $result $::errorCode
}
-result {1 {operand does not fit in one byte} {TCL ASSEM 1BYTE}}
-cleanup {rename x {}; unset result}
}
test assemble-14.6 {incrStkImm} {
-body {
proc x {} {
set y 1
list [assemble {push y; incrStkImm -0x80}] \
[assemble {push y; incrStkImm 0x7f}]
}
x
}
-result {-127 0}
-cleanup {rename x {}}
}
test assemble-14.7 {incrArrayStkImm} {
-body {
proc x {} {
set a(b) 5
assemble {push a; push b; incrArrayStkImm 3}
}
x
}
-result 8
-cleanup {rename x {}}
}
# assemble-15 - listIndexImm
test assemble-15.1 {listIndexImm - wrong # args} -body {
assemble {listIndexImm}
} -returnCodes error -match glob -result {wrong # args*}
test assemble-15.2 {listIndexImm - wrong # args} -body {
assemble {listIndexImm too many}
} -returnCodes error -match glob -result {wrong # args*}
test assemble-15.3 {listIndexImm - bad substitution} -body {
list [catch {assemble {listIndexImm $foo}} result] $result $::errorCode
} -cleanup {
unset result
} -result {1 {assembly code may not contain substitutions} {TCL ASSEM NOSUBST}}
test assemble-15.4 {listIndexImm - invalid index} -body {
assemble {listIndexImm rubbish}
} -returnCodes error -match glob -result {bad index "rubbish"*}
test assemble-15.5 {listIndexImm} -body {
assemble {push {a b c}; listIndexImm 2}
} -result c
test assemble-15.6 {listIndexImm} -body {
assemble {push {a b c}; listIndexImm end-1}
} -result b
test assemble-15.7 {listIndexImm} -body {
assemble {push {a b c}; listIndexImm end}
} -result c
test assemble-15.8 {listIndexImm} -body {
assemble {push {a b c}; listIndexImm end+2}
} -result {}
test assemble-15.9 {listIndexImm} -body {
assemble {push {a b c}; listIndexImm -1-1}
} -result {}
# assemble-16 - invokeStk
test assemble-16.1 {invokeStk - wrong # args} {
-body {
assemble {invokeStk}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-16.2 {invokeStk - wrong # args} {
-body {
assemble {invokeStk too many}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-16.3 {invokeStk - not a number} {
-body {
proc x {} {
assemble {invokeStk rubbish}
}
x
}
-returnCodes error
-result {expected integer but got "rubbish"}
-cleanup {rename x {}}
}
test assemble-16.4 {invokeStk - no operands} {
-body {
proc x {} {
assemble {invokeStk 0}
}
list [catch x result] $result $::errorCode
}
-result {1 {operand must be positive} {TCL ASSEM POSITIVE}}
-cleanup {rename x {}; unset result}
}
test assemble-16.5 {invokeStk1} {
-body {
tcl::unsupported::assemble {push concat; push 1; push 2; invokeStk 3}
}
-result {1 2}
}
test assemble-16.6 {invokeStk4} {
-body {
proc x {n} {
set code {push concat}
set shouldbe {}
for {set i 1} {$i < $n} {incr i} {
append code \n {push a} $i
lappend shouldbe a$i
}
append code \n {invokeStk} { } $n
set is [assemble $code]
expr {$is eq $shouldbe}
}
list [x 254] [x 255] [x 256] [x 257]
}
-result {1 1 1 1}
-cleanup {rename x {}}
}
# assemble-17 -- jumps and labels
test assemble-17.1 {label, wrong # args} {
-body {
assemble {label}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-17.2 {label, wrong # args} {
-body {
assemble {label too many}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-17.3 {label, bad subst} {
-body {
list [catch {assemble {label $foo}} result] $result $::errorCode
}
-result {1 {assembly code may not contain substitutions} {TCL ASSEM NOSUBST}}
-cleanup {unset result}
}
test assemble-17.4 {duplicate label} {
-body {
list [catch {assemble {label foo; label foo}} result] \
$result $::errorCode
}
-result {1 {duplicate definition of label "foo"} {TCL ASSEM DUPLABEL foo}}
}
test assemble-17.5 {jump, wrong # args} {
-body {
assemble {jump}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-17.6 {jump, wrong # args} {
-body {
assemble {jump too many}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-17.7 {jump, bad subst} {
-body {
list [catch {assemble {jump $foo}} result] $result $::errorCode
}
-result {1 {assembly code may not contain substitutions} {TCL ASSEM NOSUBST}}
-cleanup {unset result}
}
test assemble-17.8 {jump - ahead and back} {
-body {
assemble {
jump three
label one
push a
jump four
label two
push b
jump six
label three
push c
jump five
label four
push d
jump two
label five
push e
jump one
label six
push f
concat 6
}
}
-result ceadbf
}
test assemble-17.9 {jump - resolve a label multiple times} {
-body {
proc x {} {
set case 0
set result {}
assemble {
jump common
label zero
pop
incrImm case 1
pop
push a
append result
pop
jump common
label one
pop
incrImm case 1
pop
push b
append result
pop
jump common
label common
load case
dup
push 0
eq
jumpTrue zero
dup
push 1
eq
jumpTrue one
dup
push 2
eq
jumpTrue two
dup
push 3
eq
jumpTrue three
label two
pop
incrImm case 1
pop
push c
append result
pop
jump common
label three
pop
incrImm case 1
pop
push d
append result
}
}
x
}
-result abcd
-cleanup {rename x {}}
}
test assemble-17.10 {jump4 needed} {
-body {
assemble "push x; jump one; label two; [string repeat {dup; pop;} 128]
jump three; label one; jump two; label three"
}
-result x
}
test assemble-17.11 {jumpTrue} {
-body {
proc x {y} {
assemble {
load y
jumpTrue then
push no
jump else
label then
push yes
label else
}
}
list [x 0] [x 1]
}
-result {no yes}
-cleanup {rename x {}}
}
test assemble-17.12 {jumpFalse} {
-body {
proc x {y} {
assemble {
load y
jumpFalse then
push no
jump else
label then
push yes
label else
}
}
list [x 0] [x 1]
}
-result {yes no}
-cleanup {rename x {}}
}
test assemble-17.13 {jump to undefined label} {
-body {
list [catch {assemble {jump nowhere}} result] $result $::errorCode
}
-result {1 {undefined label "nowhere"} {TCL ASSEM NOLABEL nowhere}}
}
test assemble-17.14 {jump to undefined label, line number correct?} {
-body {
catch {assemble {#1
#2
#3
jump nowhere
#5
#6
}}
set ::errorInfo
}
-match glob
-result {*"assemble" body, line 4*}
}
test assemble-17.15 {multiple passes of code resizing} {
-setup {
set body {
push -
}
for {set i 0} {$i < 14} {incr i} {
append body "label a" $i \
"; push a; concat 2; nop; nop; jump b" \
$i \n
}
append body {label a14; push a; concat 2; push 1; jumpTrue b14} \n
append body {label a15; push a; concat 2; push 0; jumpFalse b15} \n
for {set i 0} {$i < 15} {incr i} {
append body "label b" $i \
"; push b; concat 2; nop; nop; jump a" \
[expr {$i+1}] \n
}
append body {label c; push -; concat 2; nop; nop; nop; jump d} \n
append body {label b15; push b; concat 2; nop; nop; jump c} \n
append body {label d}
proc x {} [list assemble $body]
}
-body {
x
}
-cleanup {
catch {unset body}
catch {rename x {}}
}
-result -abababababababababababababababab-
}
# assemble-18 - lindexMulti
test assemble-18.1 {lindexMulti - wrong # args} {
-body {
assemble {lindexMulti}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-18.2 {lindexMulti - wrong # args} {
-body {
assemble {lindexMulti too many}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-18.3 {lindexMulti - bad subst} {
-body {
assemble {lindexMulti $foo}
}
-returnCodes error
-match glob
-result {assembly code may not contain substitutions}
}
test assemble-18.4 {lindexMulti - not a number} {
-body {
proc x {} {
assemble {lindexMulti rubbish}
}
x
}
-returnCodes error
-result {expected integer but got "rubbish"}
-cleanup {rename x {}}
}
test assemble-18.5 {lindexMulti - bad operand count} {
-body {
proc x {} {
assemble {lindexMulti 0}
}
list [catch x result] $result $::errorCode
}
-result {1 {operand must be positive} {TCL ASSEM POSITIVE}}
-cleanup {rename x {}; unset result}
}
test assemble-18.6 {lindexMulti} {
-body {
assemble {push {{a b c} {d e f} {g h j}}; lindexMulti 1}
}
-result {{a b c} {d e f} {g h j}}
}
test assemble-18.7 {lindexMulti} {
-body {
assemble {push {{a b c} {d e f} {g h j}}; push 1; lindexMulti 2}
}
-result {d e f}
}
test assemble-18.8 {lindexMulti} {
-body {
assemble {push {{a b c} {d e f} {g h j}}; push 2; push 1; lindexMulti 3}
}
-result h
}
# assemble-19 - list
test assemble-19.1 {list - wrong # args} {
-body {
assemble {list}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-19.2 {list - wrong # args} {
-body {
assemble {list too many}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-19.3 {list - bad subst} {
-body {
assemble {list $foo}
}
-returnCodes error
-match glob
-result {assembly code may not contain substitutions}
}
test assemble-19.4 {list - not a number} {
-body {
proc x {} {
assemble {list rubbish}
}
x
}
-returnCodes error
-result {expected integer but got "rubbish"}
-cleanup {rename x {}}
}
test assemble-19.5 {list - negative operand count} {
-body {
proc x {} {
assemble {list -1}
}
list [catch x result] $result $::errorCode
}
-result {1 {operand must be nonnegative} {TCL ASSEM NONNEGATIVE}}
-cleanup {rename x {}; unset result}
}
test assemble-19.6 {list - no args} {
-body {
assemble {list 0}
}
-result {}
}
test assemble-19.7 {list - 1 arg} {
-body {
assemble {push hello; list 1}
}
-result hello
}
test assemble-19.8 {list - 2 args} {
-body {
assemble {push hello; push world; list 2}
}
-result {hello world}
}
# assemble-20 - lsetFlat
test assemble-20.1 {lsetFlat - wrong # args} {
-body {
assemble {lsetFlat}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-20.2 {lsetFlat - wrong # args} {
-body {
assemble {lsetFlat too many}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-20.3 {lsetFlat - bad subst} {
-body {
assemble {lsetFlat $foo}
}
-returnCodes error
-match glob
-result {assembly code may not contain substitutions}
}
test assemble-20.4 {lsetFlat - not a number} {
-body {
proc x {} {
assemble {lsetFlat rubbish}
}
x
}
-returnCodes error
-result {expected integer but got "rubbish"}
-cleanup {rename x {}}
}
test assemble-20.5 {lsetFlat - negative operand count} {
-body {
proc x {} {
assemble {lsetFlat 1}
}
list [catch x result] $result $::errorCode
}
-result {1 {operand must be >=2} {TCL ASSEM OPERAND>=2}}
-cleanup {rename x {}; unset result}
}
test assemble-20.6 {lsetFlat} {
-body {
assemble {push b; push a; lsetFlat 2}
}
-result b
}
test assemble-20.7 {lsetFlat} {
-body {
assemble {push 1; push d; push {a b c}; lsetFlat 3}
}
-result {a d c}
}
# assemble-21 - over
test assemble-21.1 {over - wrong # args} {
-body {
assemble {over}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-21.2 {over - wrong # args} {
-body {
assemble {over too many}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-21.3 {over - bad subst} {
-body {
assemble {over $foo}
}
-returnCodes error
-match glob
-result {assembly code may not contain substitutions}
}
test assemble-21.4 {over - not a number} {
-body {
proc x {} {
assemble {over rubbish}
}
x
}
-returnCodes error
-result {expected integer but got "rubbish"}
-cleanup {rename x {}}
}
test assemble-21.5 {over - negative operand count} {
-body {
proc x {} {
assemble {over -1}
}
list [catch x result] $result $::errorCode
}
-result {1 {operand must be nonnegative} {TCL ASSEM NONNEGATIVE}}
-cleanup {rename x {}; unset result}
}
test assemble-21.6 {over} {
-body {
proc x {} {
assemble {
push 1
push 2
push 3
over 0
store x
pop
pop
pop
pop
load x
}
}
x
}
-result 3
-cleanup {rename x {}}
}
test assemble-21.7 {over} {
-body {
proc x {} {
assemble {
push 1
push 2
push 3
over 2
store x
pop
pop
pop
pop
load x
}
}
x
}
-result 1
-cleanup {rename x {}}
}
# assemble-22 - reverse
test assemble-22.1 {reverse - wrong # args} {
-body {
assemble {reverse}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-22.2 {reverse - wrong # args} {
-body {
assemble {reverse too many}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-22.3 {reverse - bad subst} {
-body {
assemble {reverse $foo}
}
-returnCodes error
-match glob
-result {assembly code may not contain substitutions}
}
test assemble-22.4 {reverse - not a number} {
-body {
proc x {} {
assemble {reverse rubbish}
}
x
}
-returnCodes error
-result {expected integer but got "rubbish"}
-cleanup {rename x {}}
}
test assemble-22.5 {reverse - negative operand count} {
-body {
proc x {} {
assemble {reverse -1}
}
list [catch x result] $result $::errorCode
}
-result {1 {operand must be nonnegative} {TCL ASSEM NONNEGATIVE}}
-cleanup {rename x {}; unset result}
}
test assemble-22.6 {reverse - zero operand count} {
-body {
proc x {} {
assemble {push 1; reverse 0}
}
x
}
-result 1
-cleanup {rename x {}}
}
test assemble-22.7 {reverse} {
-body {
proc x {} {
assemble {
push 1
push 2
push 3
reverse 1
store x
pop
pop
pop
load x
}
}
x
}
-result 3
-cleanup {rename x {}}
}
test assemble-22.8 {reverse} {
-body {
proc x {} {
assemble {
push 1
push 2
push 3
reverse 3
store x
pop
pop
pop
load x
}
}
x
}
-result 1
-cleanup {rename x {}}
}
# assemble-23 - ASSEM_BOOL (strmatch, unsetStk, unsetArrayStk)
test assemble-23.1 {strmatch - wrong # args} {
-body {
assemble {strmatch}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-23.2 {strmatch - wrong # args} {
-body {
assemble {strmatch too many}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-23.3 {strmatch - bad subst} {
-body {
assemble {strmatch $foo}
}
-returnCodes error
-match glob
-result {assembly code may not contain substitutions}
}
test assemble-23.4 {strmatch - not a boolean} {
-body {
proc x {} {
assemble {strmatch rubbish}
}
x
}
-returnCodes error
-result {expected boolean value but got "rubbish"}
-cleanup {rename x {}}
}
test assemble-23.5 {strmatch} {
-body {
proc x {a b} {
list [assemble {load a; load b; strmatch 0}] \
[assemble {load a; load b; strmatch 1}]
}
list [x foo*.grill fengbar.grill] [x foo*.grill foobar.grill] [x foo*.grill FOOBAR.GRILL]
}
-result {{0 0} {1 1} {0 1}}
-cleanup {rename x {}}
}
test assemble-23.6 {unsetStk} {
-body {
proc x {} {
set a {}
assemble {push a; unsetStk false}
info exists a
}
x
}
-result 0
-cleanup {rename x {}}
}
test assemble-23.7 {unsetStk} {
-body {
proc x {} {
assemble {push a; unsetStk false}
info exists a
}
x
}
-result 0
-cleanup {rename x {}}
}
test assemble-23.8 {unsetStk} {
-body {
proc x {} {
assemble {push a; unsetStk true}
info exists a
}
x
}
-returnCodes error
-result {can't unset "a": no such variable}
-cleanup {rename x {}}
}
test assemble-23.9 {unsetArrayStk} {
-body {
proc x {} {
set a(b) {}
assemble {push a; push b; unsetArrayStk false}
info exists a(b)
}
x
}
-result 0
-cleanup {rename x {}}
}
test assemble-23.10 {unsetArrayStk} {
-body {
proc x {} {
assemble {push a; push b; unsetArrayStk false}
info exists a(b)
}
x
}
-result 0
-cleanup {rename x {}}
}
test assemble-23.11 {unsetArrayStk} {
-body {
proc x {} {
assemble {push a; push b; unsetArrayStk true}
info exists a(b)
}
x
}
-returnCodes error
-result {can't unset "a(b)": no such variable}
-cleanup {rename x {}}
}
# assemble-24 -- ASSEM_BOOL_LVT4 (unset; unsetArray)
test assemble-24.1 {unset - wrong # args} {
-body {
assemble {unset one}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-24.2 {unset - wrong # args} {
-body {
assemble {unset too many args}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-24.3 {unset - bad subst -arg 1} {
-body {
assemble {unset $foo bar}
}
-returnCodes error
-match glob
-result {assembly code may not contain substitutions}
}
test assemble-24.4 {unset - not a boolean} {
-body {
proc x {} {
assemble {unset rubbish trash}
}
x
}
-returnCodes error
-result {expected boolean value but got "rubbish"}
-cleanup {rename x {}}
}
test assemble-24.5 {unset - bad subst - arg 2} {
-body {
assemble {unset true $bar}
}
-returnCodes error
-result {assembly code may not contain substitutions}
}
test assemble-24.6 {unset - nonlocal var} {
-body {
assemble {unset true ::foo::bar}
}
-returnCodes error
-result {variable "::foo::bar" is not local}
}
test assemble-24.7 {unset} {
-body {
proc x {} {
set a {}
assemble {unset false a}
info exists a
}
x
}
-result 0
-cleanup {rename x {}}
}
test assemble-24.8 {unset} {
-body {
proc x {} {
assemble {unset false a}
info exists a
}
x
}
-result 0
-cleanup {rename x {}}
}
test assemble-24.9 {unset} {
-body {
proc x {} {
assemble {unset true a}
info exists a
}
x
}
-returnCodes error
-result {can't unset "a": no such variable}
-cleanup {rename x {}}
}
test assemble-24.10 {unsetArray} {
-body {
proc x {} {
set a(b) {}
assemble {push b; unsetArray false a}
info exists a(b)
}
x
}
-result 0
-cleanup {rename x {}}
}
test assemble-24.11 {unsetArray} {
-body {
proc x {} {
assemble {push b; unsetArray false a}
info exists a(b)
}
x
}
-result 0
-cleanup {rename x {}}
}
test assemble-24.12 {unsetArray} {
-body {
proc x {} {
assemble {push b; unsetArray true a}
info exists a(b)
}
x
}
-returnCodes error
-result {can't unset "a(b)": no such variable}
-cleanup {rename x {}}
}
# assemble-25 - dict get
test assemble-25.1 {dict get - wrong # args} {
-body {
assemble {dictGet}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-25.2 {dict get - wrong # args} {
-body {
assemble {dictGet too many}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-25.3 {dictGet - bad subst} {
-body {
assemble {dictGet $foo}
}
-returnCodes error
-match glob
-result {assembly code may not contain substitutions}
}
test assemble-25.4 {dict get - not a number} {
-body {
proc x {} {
assemble {dictGet rubbish}
}
x
}
-returnCodes error
-result {expected integer but got "rubbish"}
-cleanup {rename x {}}
}
test assemble-25.5 {dictGet - negative operand count} {
-body {
proc x {} {
assemble {dictGet 0}
}
list [catch x result] $result $::errorCode
}
-result {1 {operand must be positive} {TCL ASSEM POSITIVE}}
-cleanup {rename x {}; unset result}
}
test assemble-25.6 {dictGet - 1 index} {
-body {
assemble {push {a 1 b 2}; push a; dictGet 1}
}
-result 1
}
# assemble-26 - dict set
test assemble-26.1 {dict set - wrong # args} {
-body {
assemble {dictSet 1}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-26.2 {dict get - wrong # args} {
-body {
assemble {dictSet too many args}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-26.3 {dictSet - bad subst} {
-body {
assemble {dictSet 1 $foo}
}
-returnCodes error
-match glob
-result {assembly code may not contain substitutions}
}
test assemble-26.4 {dictSet - not a number} {
-body {
proc x {} {
assemble {dictSet rubbish foo}
}
x
}
-returnCodes error
-result {expected integer but got "rubbish"}
-cleanup {rename x {}}
}
test assemble-26.5 {dictSet - zero operand count} {
-body {
proc x {} {
assemble {dictSet 0 foo}
}
list [catch x result] $result $::errorCode
}
-result {1 {operand must be positive} {TCL ASSEM POSITIVE}}
-cleanup {rename x {}; unset result}
}
test assemble-26.6 {dictSet - bad local} {
-body {
proc x {} {
assemble {dictSet 1 ::foo::bar}
}
list [catch x result] $result $::errorCode
}
-result {1 {variable "::foo::bar" is not local} {TCL ASSEM NONLOCAL ::foo::bar}}
-cleanup {rename x {}; unset result}
}
test assemble-26.7 {dictSet} {
-body {
proc x {} {
set dict {a 1 b 2 c 3}
assemble {push b; push 4; dictSet 1 dict}
}
x
}
-result {a 1 b 4 c 3}
-cleanup {rename x {}}
}
# assemble-27 - dictUnset
test assemble-27.1 {dictUnset - wrong # args} {
-body {
assemble {dictUnset 1}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-27.2 {dictUnset - wrong # args} {
-body {
assemble {dictUnset too many args}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-27.3 {dictUnset - bad subst} {
-body {
assemble {dictUnset 1 $foo}
}
-returnCodes error
-match glob
-result {assembly code may not contain substitutions}
}
test assemble-27.4 {dictUnset - not a number} {
-body {
proc x {} {
assemble {dictUnset rubbish foo}
}
x
}
-returnCodes error
-result {expected integer but got "rubbish"}
-cleanup {rename x {}}
}
test assemble-27.5 {dictUnset - zero operand count} {
-body {
proc x {} {
assemble {dictUnset 0 foo}
}
list [catch x result] $result $::errorCode
}
-result {1 {operand must be positive} {TCL ASSEM POSITIVE}}
-cleanup {rename x {}; unset result}
}
test assemble-27.6 {dictUnset - bad local} {
-body {
proc x {} {
assemble {dictUnset 1 ::foo::bar}
}
list [catch x result] $result $::errorCode
}
-result {1 {variable "::foo::bar" is not local} {TCL ASSEM NONLOCAL ::foo::bar}}
-cleanup {rename x {}; unset result}
}
test assemble-27.7 {dictUnset} {
-body {
proc x {} {
set dict {a 1 b 2 c 3}
assemble {push b; dictUnset 1 dict}
}
x
}
-result {a 1 c 3}
-cleanup {rename x {}}
}
# assemble-28 - dictIncrImm
test assemble-28.1 {dictIncrImm - wrong # args} {
-body {
assemble {dictIncrImm 1}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-28.2 {dictIncrImm - wrong # args} {
-body {
assemble {dictIncrImm too many args}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-28.3 {dictIncrImm - bad subst} {
-body {
assemble {dictIncrImm 1 $foo}
}
-returnCodes error
-match glob
-result {assembly code may not contain substitutions}
}
test assemble-28.4 {dictIncrImm - not a number} {
-body {
proc x {} {
assemble {dictIncrImm rubbish foo}
}
x
}
-returnCodes error
-result {expected integer but got "rubbish"}
-cleanup {rename x {}}
}
test assemble-28.5 {dictIncrImm - bad local} {
-body {
proc x {} {
assemble {dictIncrImm 1 ::foo::bar}
}
list [catch x result] $result $::errorCode
}
-result {1 {variable "::foo::bar" is not local} {TCL ASSEM NONLOCAL ::foo::bar}}
-cleanup {rename x {}; unset result}
}
test assemble-28.6 {dictIncrImm} {
-body {
proc x {} {
set dict {a 1 b 2 c 3}
assemble {push b; dictIncrImm 42 dict}
}
x
}
-result {a 1 b 44 c 3}
-cleanup {rename x {}}
}
# assemble-29 - ASSEM_REGEXP
test assemble-29.1 {regexp - wrong # args} {
-body {
assemble {regexp}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-29.2 {regexp - wrong # args} {
-body {
assemble {regexp too many}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-29.3 {regexp - bad subst} {
-body {
assemble {regexp $foo}
}
-returnCodes error
-match glob
-result {assembly code may not contain substitutions}
}
test assemble-29.4 {regexp - not a boolean} {
-body {
proc x {} {
assemble {regexp rubbish}
}
x
}
-returnCodes error
-result {expected boolean value but got "rubbish"}
-cleanup {rename x {}}
}
test assemble-29.5 {regexp} {
-body {
assemble {push br.*br; push abracadabra; regexp false}
}
-result 1
}
test assemble-29.6 {regexp} {
-body {
assemble {push br.*br; push aBRacadabra; regexp false}
}
-result 0
}
test assemble-29.7 {regexp} {
-body {
assemble {push br.*br; push aBRacadabra; regexp true}
}
-result 1
}
# assemble-30 - Catches
test assemble-30.1 {simplest possible catch} {
-body {
proc x {} {
assemble {
beginCatch @bad
push error
push testing
invokeStk 2
pop
push 0
jump @ok
label @bad
push 1; # should be pushReturnCode
label @ok
endCatch
}
}
x
}
-result 1
-cleanup {rename x {}}
}
test assemble-30.2 {catch in external catch conntext} {
-body {
proc x {} {
list [catch {
assemble {
beginCatch @bad
push error
push testing
invokeStk 2
pop
push 0
jump @ok
label @bad
pushReturnCode
label @ok
endCatch
}
} result] $result
}
x
}
-result {0 1}
-cleanup {rename x {}}
}
test assemble-30.3 {embedded catches} {
-body {
proc x {} {
list [catch {
assemble {
beginCatch @bad
push error
eval { list [catch {error whatever} result] $result }
invokeStk 2
push 0
reverse 2
jump @done
label @bad
pushReturnCode
pushResult
label @done
endCatch
list 2
}
} result2] $result2
}
x
}
-result {0 {1 {1 whatever}}}
-cleanup {rename x {}}
}
test assemble-30.4 {throw in wrong context} {
-body {
proc x {} {
list [catch {
assemble {
beginCatch @bad
push error
eval { list [catch {error whatever} result] $result }
invokeStk 2
push 0
reverse 2
jump @done
label @bad
load x
pushResult
label @done
endCatch
list 2
}
} result] $result $::errorCode [split $::errorInfo \n]
}
x
}
-match glob
-result {1 {"loadScalar1" instruction may not appear in a context where an exception has been caught and not disposed of.} {TCL ASSEM BADTHROW} {{"loadScalar1" instruction may not appear in a context where an exception has been caught and not disposed of.} { in assembly code between lines 10 and 15}*}}
-cleanup {rename x {}}
}
test assemble-30.5 {unclosed catch} {
-body {
proc x {} {
assemble {
beginCatch @error
push 0
jump @done
label @error
push 1
label @done
push ""
pop
}
}
list [catch {x} result] $result $::errorCode $::errorInfo
}
-match glob
-result {1 {catch still active on exit from assembly code} {TCL ASSEM UNCLOSEDCATCH} {catch still active on exit from assembly code
("assemble" body, line 2)*}}
-cleanup {rename x {}}
}
test assemble-30.6 {inconsistent catch contexts} {
-body {
proc x {y} {
assemble {
load y
jumpTrue @inblock
beginCatch @error
label @inblock
push 0
jump @done
label @error
push 1
label @done
}
}
list [catch {x 2} result] $::errorCode $::errorInfo
}
-match glob
-result {1 {TCL ASSEM BADCATCH} {execution reaches an instruction in inconsistent exception contexts
("assemble" body, line 5)*}}
-cleanup {rename x {}}
}
# assemble-31 - Jump tables
test assemble-31.1 {jumpTable, wrong # args} {
-body {
assemble {jumpTable}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-31.2 {jumpTable, wrong # args} {
-body {
assemble {jumpTable too many}
}
-returnCodes error
-match glob
-result {wrong # args*}
}
test assemble-31.3 {jumpTable - bad subst} {
-body {
assemble {jumpTable $foo}
}
-returnCodes error
-match glob
-result {assembly code may not contain substitutions}
}
test assemble-31.4 {jumptable - not a list} {
-body {
assemble {jumpTable \{rubbish}
}
-returnCodes error
-result {unmatched open brace in list}
}
test assemble-31.5 {jumpTable, badly structured} {
-body {
list [catch {assemble {
# line 2
jumpTable {one two three};# line 3
}} result] \
$result $::errorCode $::errorInfo
}
-match glob
-result {1 {jump table must have an even number of list elements} {TCL ASSEM BADJUMPTABLE} {jump table must have an even number of list elements*("assemble" body, line 3)*}}
}
test assemble-31.6 {jumpTable, missing symbol} {
-body {
list [catch {assemble {
# line 2
jumpTable {1 a};# line 3
}} result] \
$result $::errorCode $::errorInfo
}
-match glob
-result {1 {undefined label "a"} {TCL ASSEM NOLABEL a} {undefined label "a"*("assemble" body, line 3)*}}
}
test assemble-31.7 {jumptable, actual example} {
-setup {
proc x {} {
set result {}
for {set i 0} {$i < 5} {incr i} {
lappend result [assemble {
load i
jumpTable {1 @one 2 @two 3 @three}
push {none of the above}
jump @done
label @one
push one
jump @done
label @two
push two
jump @done
label @three
push three
label @done
}]
}
set tcl_traceCompile 2
set result
}
}
-body x
-result {{none of the above} one two three {none of the above}}
-cleanup {set tcl_traceCompile 0; rename x {}}
}
test assemble-40.1 {unbalanced stack} {
-body {
list \
[catch {
assemble {
push 3
dup
mult
push 4
dup
mult
pop
expon
}
} result] $result $::errorInfo
}
-result {1 {stack underflow} {stack underflow
in assembly code between lines 1 and end of assembly code*}}
-match glob
-returnCodes ok
}
test assemble-40.2 {unbalanced stack} {*}{
-body {
list \
[catch {
assemble {
label a
push {}
label b
pop
label c
pop
label d
push {}
}
} result] $result $::errorInfo
}
-result {1 {stack underflow} {stack underflow
in assembly code between lines 7 and 9*}}
-match glob
-returnCodes ok
}
test assemble-41.1 {Inconsistent stack usage} {*}{
-body {
proc x {y} {
assemble {
load y
jumpFalse else
push 0
jump then
label else
push 1
push 2
label then
pop
}
}
catch {x 1}
set errorInfo
}
-match glob
-result {inconsistent stack depths on two execution paths
("assemble" body, line 10)*}
}
test assemble-41.2 {Inconsistent stack, jumptable and default} {
-body {
proc x {y} {
assemble {
load y
jumpTable {0 else}
push 0
label else
pop
}
}
catch {x 1}
set errorInfo
}
-match glob
-result {inconsistent stack depths on two execution paths
("assemble" body, line 6)*}
}
test assemble-41.3 {Inconsistent stack, two legs of jumptable} {
-body {
proc x {y} {
assemble {
load y
jumpTable {0 no 1 yes}
label no
push 0
label yes
pop
}
}
catch {x 1}
set errorInfo
}
-match glob
-result {inconsistent stack depths on two execution paths
("assemble" body, line 7)*}
}
test assemble-50.1 {Ulam's 3n+1 problem, TAL implementation} {
-body {
proc ulam {n} {
assemble {
load n; # max
dup; # max n
jump start; # max n
label loop; # max n
over 1; # max n max
over 1; # max in max n
ge; # man n max>=n
jumpTrue skip; # max n
reverse 2; # n max
pop; # n
dup; # n n
label skip; # max n
dup; # max n n
push 2; # max n n 2
mod; # max n n%2
jumpTrue odd; # max n
push 2; # max n 2
div; # max n/2 -> max n
jump start; # max n
label odd; # max n
push 3; # max n 3
mult; # max 3*n
push 1; # max 3*n 1
add; # max 3*n+1
label start; # max n
dup; # max n n
push 1; # max n n 1
neq; # max n n>1
jumpTrue loop; # max n
pop; # max
}
}
set result {}
for {set i 1} {$i < 30} {incr i} {
lappend result [ulam $i]
}
set result
}
-result {1 2 16 4 16 16 52 8 52 16 52 16 40 52 160 16 52 52 88 20 64 52 160 24 88 40 9232 52 88}
}
test assemble-51.1 {memory leak testing} memory {
leaktest {
apply {{} {assemble {push hello}}}
}
} 0
test assemble-51.2 {memory leak testing} memory {
leaktest {
apply {{{x 0}} {assemble {incrImm x 1}}}
}
} 0
test assemble-51.3 {memory leak testing} memory {
leaktest {
apply {{n} {
assemble {
load n; # max
dup; # max n
jump start; # max n
label loop; # max n
over 1; # max n max
over 1; # max in max n
ge; # man n max>=n
jumpTrue skip; # max n
reverse 2; # n max
pop; # n
dup; # n n
label skip; # max n
dup; # max n n
push 2; # max n n 2
mod; # max n n%2
jumpTrue odd; # max n
push 2; # max n 2
div; # max n/2 -> max n
jump start; # max n
label odd; # max n
push 3; # max n 3
mult; # max 3*n
push 1; # max 3*n 1
add; # max 3*n+1
label start; # max n
dup; # max n n
push 1; # max n n 1
neq; # max n n>1
jumpTrue loop; # max n
pop; # max
}
}} 1
}
} 0
test assemble-51.4 {memory leak testing} memory {
leaktest {
catch {
apply {{} {
assemble {reverse polish notation}
}}
}
}
} 0
test assemble-52.1 {Bug 3154ea2759} {
apply {{} {
# Needs six exception ranges to force the range allocations to use the
# malloced store.
::tcl::unsupported::assemble {
beginCatch @badLabel
push error
push testing
invokeStk 2
pop
push 0
jump @okLabel
label @badLabel
push 1; # should be pushReturnCode
label @okLabel
endCatch
pop
beginCatch @badLabel2
push error
push testing
invokeStk 2
pop
push 0
jump @okLabel2
label @badLabel2
push 1; # should be pushReturnCode
label @okLabel2
endCatch
pop
beginCatch @badLabel3
push error
push testing
invokeStk 2
pop
push 0
jump @okLabel3
label @badLabel3
push 1; # should be pushReturnCode
label @okLabel3
endCatch
pop
beginCatch @badLabel4
push error
push testing
invokeStk 2
pop
push 0
jump @okLabel4
label @badLabel4
push 1; # should be pushReturnCode
label @okLabel4
endCatch
pop
beginCatch @badLabel5
push error
push testing
invokeStk 2
pop
push 0
jump @okLabel5
label @badLabel5
push 1; # should be pushReturnCode
label @okLabel5
endCatch
pop
beginCatch @badLabel6
push error
push testing
invokeStk 2
pop
push 0
jump @okLabel6
label @badLabel6
push 1; # should be pushReturnCode
label @okLabel6
endCatch
pop
}
}}
} {}; # must not crash
rename fillTables {}
rename assemble {}
::tcltest::cleanupTests
return
# Local Variables:
# mode: tcl
# fill-column: 78
# End: