# for general test use best name except for j, c, +
# test vectorization
3,4 2+ -> [5,6]

# test input arg
:+ -> 1554
-3 -> -774
200 mdup !+ > -> 977 200

# test op capitalization
4j 3c J 2j 1c Cons -> [[1,2],[3,4]]

# Test parse
1 mdup 1> -> 1:3 (mdup) excessive values in block and implicit ops not yet implemented

# Test data parse
1, -> [1]
1,2, -> [1,2]
# 1,,2 ->
# 1,, ->
1,2,3 -> [1,2,3]
1,2,,3 -> [[1,2],[3]]
1,,3 -> [[1],[3]]
1,, -> [[1]]
1,,,2 -> [[[1]],[[2]]]
"1","2","3" -> ["1","2","3"]
"1", -> ["1"]
"1","2",,"3" -> [["1","2"],["3"]]
"1",,"3" -> [["1"],["3"]]
"1",, -> [["1"]]
1,"ab" -> ["1","ab"]
1,'a -> ["1","a"]
'a,"bc" -> ["a","bc"]
11,, ,,22 -> [[11],[],[22]]
1, ,2 -> found ", ," invalid data format

# data parse after splitting token
1j2,3 -> [1] [2,3]

# comma use after splitting token
1nj, -> [[0]]

# Test comments
10,2# 0 -> [10,2]
10,2#0 -> 12 0

# Test unvec
1,2,,3,4 head, -> [1,2]
1,2,,3,4J, H, -> [[1,2],[3,4]]
5,6,,7,8J, 1,2,,3,4 C, -> [[[1,2],[3,4]],[[5,6],[7,8]]]
1 2-, -> 1:4 (-, sub) extra , used

# Test empty program
-> 777

# Test blocks
5 > -> 1:3 (>) unmatched >

# Test arg use
3 mdup $ + > -> 6 3

# Test char
'a -> 'a'
"asdf" -> "asdf"
"123","asdf" -> ["123","asdf"]
' -> 1:1 (') empty char
"a -> "a"
" -> ""

# Test x spec
1,2,3,,4,5,6 sum -> [6,15]

# Test escapes (todo)

# Test overload
"asdf" 1 + -> "bteg"
"bteg" 1 - -> "asdf"

# Test adjacent ids
"asdf"th -> 's'
#'
"asdf"t10+ -> "}np"
"asdf"t0010 -> "sdf" 0 0 10

# Test truthiness
1,0 not -> [0,1]
"a\n\0 ." not -> [0,1,1,1,0]
# todo chars 9 and 11
"a","" Not -> [0,1]

# Test meta ops #############
7 dup + -> 14
10 mdup 1+> 1-* -> 99

# ! outer
! -> 1:1 (!) no outer stack in main
100 7 mdup !* > + -> 707
100 0 foldr 1,2,3,4+!+ > -> 410

# Test var stack
5 [ 6 ] -> 5 6 5
5 ] -> 1:3 (]) var stack is empty, cannot pop

# Test vars
4~xyz xyz+ -> 8
4~3 3+ -> 8
3~+ + -> 3 3
3 1 cons ~ 3 5 take -> [1,1,1,1,1]

# Test op can still be used with , after assignment
5~j 1,2j, -> 5 [[1,2]]

# Test register
1@ 2@ 3@ -> 1 3 2 3 3
1~@ 2 @ -> 1 2 1

# Test inspect
1 show -> "1"
1j show -> "[1]"
nil show -> "[]"
nil J show -> "[[]]"

# Test nil
nil J N, -> 0
nil J Tail N, -> 1
nil J ZeroPad 2 Take -> [[],[]]

# Test del
5 del 6 -> 6

# Test type
1 type -> "int"
1j type -> "[int]"
'c type -> "char"
#'
"" type -> "[char]"
nil type -> "[]"

# Test that empty type auto increases rank
nil "a" Cons -> ["a"]

nil 1+ -> 1:6 (+ add) op is not defined for base types: empty int

# Test implicit >
iterate0 1+ negate 5 take -> [-1,-2,-3,-4,-5]
5;+2 -> 7 5

# Test implicit args
a -> [777,777]

# Test empty block
5;> -> 5 5

# implicit arg and rotation trick
a a 1 -> [1,777,777]

# implicit arg inside block
1; a > -> [1,1] 1

# implicit arg still used inside function that must end at end of program
5;* -> 25 5

# first ; must match > because no other block openers to match it
1; ) a > 5 -> [1,2] 1 5
1; ) a > m5,6+ -> [1,2] 1 11
m 5,6+ 1; ) a > -> 1:1 (m) excessive values in block and implicit ops not yet implemented

# test complex example of this (has implicit use after explicit (non nested))
41 I h;2/j> 2%ja > ;Tl>hw 41i2/:w2% -> [1,0,0,1,0,1] [1,0,0,1,0,1]

# fake parse doens't mess up @ registers
1; )@ > -> 2 1

# test infinite type
meld just -> 1:6 (just) cannot construct the infinite type
# inner push/pop
0 iterate [ 1+ > 5 keep  ] 6 keep -> [0,1,2,3,4] [0,1,2,3,4,5]
0 iterate ~ peek 1+ > 5 keep  peek 6 keep -> [0,1,2,3,4] [0,1,2,3,4,5]

# Test block using ops ######

# iterate
0 iterate 1,2,3+ > -> [0,1,3,6]
0 iterate dup 1 c + > t t t tail t t t head -> 13
1,2 Iterate 3,4 c > -> [[1,2],[3,1,2],[4,3,1,2]]
0 iterate 1,2,3,,4,5,6 + -> [[0,1,3,6],[0,4,9,15]]

# foldr
0 foldr 1,2,3+ > -> 6
1,2 Foldr 3,4 c > -> [3,4,1,2]
0 foldr 1,2,,3,4+ > -> [3,7]
0 foldr 1,2,,3,4 mdup j > c+ > -> [[2,4],[6,8]]
0 foldr 1,2,3,,4,5,6 + -> [6,15]

# iterate0
iterate0 1+ > 5 take -> [1,2,3,4,5]
Iterate0 "ab","cd","ef" append > -> ["ab","abcd","abcdef"]
Expand "ab","cd","ef" append > -> ["ab","abcd","abcdef"]
iterate0 'a cons > 5 take -> "a a a"
iterate0 1,2,3,,4,5,6 + -> [[1,3,6],[4,9,15]]
expand > -> [0,0,0...

# foldr0
foldr0 1,2,3 + > -> 6
Foldr0 "ab","cd","ef" append > -> "efcdab"
foldr0 1,2,3,,4,5,6 + -> [6,15]
Meld "ab","cd","ef" append > -> "efcdab"

# superpad
1,2,3 Iterate tail > 5 Take -> [[1,2,3],[2,3],[3],[],[]]
1,2,3 J Iterate tail > 5 Take -> [[[1,2,3],[2,3],[3],[],[]]]
1,2,3 j Iterate, Tail > 5 Take, -> [[[1],[2],[3]],[[2],[3]],[[3]],[],[]]

0 iterate [ 1,2,,4,5 + > del ] 5 K -> [[0,1,3],[0,4,9],[],[],[]]
0 iterate [ 1,2,,4,5,,,6 + > del ] 5 K, 4 K -> [[[0,1,3],[0,4,9],[],[]],[[0,6],[],[],[]],[[],[],[],[]],[[],[],[],[]],[[],[],[],[]]]

# Test ops ##################
# head
"asdf" head -> 'a'
"" head 2 -> ' ' 2
1 j tail head -> 0
# nil head -> todo

# tail
"asdf" tail -> "sdf"
"" tail -> ""

# arithmetic
1 2+ -> 3
1 2- -> -1
1 2* -> 2
1 2/ 2 2/ -> 0 1
1 0/ -> 0
1 negate -> -1
1 2% 2 2% 1 negate 3% -> 1 0 2
3 0 % -> 0
'a 10 % -> 7
2 3^ -> 8
0 0^ -> 1

8,9,10 sqrt -> [2,3,3]
0 sqrt -> 0
1_ sqrt -> negative square root

5 countTo 3- 1 negate ^ -> [-1,-1,0,1,0]
5 countTo 3- 2 negate ^ -> [0,1,0,1,0]

# sum
1,2,3 sum -> 6
2j tail sum -> 0
# todo
# "abc" sum -> 294
1,2,3,4 prod -> 24
2j tail prod -> 1


# chr
100 '\0+ -> 'd'

# str
123 str 1+ -> "234"

# read
"" read -> 0
"b122a" read 1+ -> 123

# readAll
"1 2 ab3 -4 --5 ---6" readAll -> [1,2,3,-4,5,-6]

'd '\0- -> 100

# "\nab\nc\n\nd\n" lines -> ["","ab","c","","d"]
# "1\n\n" lines -> ["1",""]

" \n\0a b " strip -> "a b"

"ab" 5 replicate -> "ababababab"

"ab","cd" " " * -> "ab cd"

" ab  cd e " " " cut -> ["","ab","","cd","e",""]

" ab  cd e " " " split -> ["ab","cd","e"]

"ab","cd","ef" " ",".","-" join -> "ab cd.ef"
"ab","cd","ef" " ","." join -> "ab cd.ef"
"ab","cd","ef" " "J join -> "ab cd"

# if
0 1 2 ifElse 1 1 2 ifElse -> 2 1
" a" 1 2 ifElse -> [2,1]

# take
"abcde" 2 take -> "ab"
"ab" 10 take -> "ab"

# drop
"abcde" 2 drop -> "cde"
"abc" 5 drop -> ""

# get
"abc" 1 get -> 'b'
1,2,3 4 get -> 0

# repeat
1 repeat 3 take -> [1,1,1]

# append
"abc" "123" append -> "abc123"

# or
1 2 or -> 1
0 2 or -> 2
1j tail 2j Or -> [2]
"" "a" Or -> "a"

100 "ab" or -> "10"
0 "ab" Or -> "ab"
1 "ab" Or -> "1"
0j "ab" Or -> ["ab"]
0 1drop "ab" Or dup type -> [] "[[char]]"

# equal
0,1 0,2 equal -> [1,0]
0,1 0,1 Equal -> 1
0,1 0,2 Equal -> 0
0,1 0j Equal -> 0
"ab" "a" Equal -> 0
"a" "ab" Equal -> 0
"ab" "ab" Equal -> 1
"ab" "ac" Equal -> 0

# lessThan
2 3 < -> 1
1 1 < -> 0
"ab" "a" LessThan -> 0
"a" "ab" LessThan -> 1
"ab" "ab" LessThan -> 0
"ab" "ac" LessThan -> 1

# reverse
"asdf" reverse -> "fdsa"

# pad
5j 1 pad 3 take -> [5,1,1]

# zeroPad
5 zeroPad -> [5,0,0...
'a zeroPad 10 take -> "a         "
5jJ ZeroPad -> [[5],[],[]...

# groupWhile
"a b"; '- cons chunkWhen tail -> ["a","b"]

# chunkWhile '
"abcd" 1,0 chunkWhen -> ["ab","c"]
"abcd" 0,1 chunkWhen -> ["a","bc"]
"" 0,1 chunkWhen -> [""]
"abc" nil chunkWhen -> ["a"]
"a","b","c" 1,0 ChunkWhen -> [["a","b"],["c"]]

# len
"asdf" len -> 4

# sortBy
"12345" "asdfe" sortBy -> "13542"
"ab","aa" : SortBy -> ["aa","ab"]

# filter
"123" "a a" filter -> "13"

# uniq
"acaabc" : debut filter -> "acb"

# transpose
"abc","1" transpose -> ["a1","b","c"]
"abc","12","xyz" transpose -> ["a1x","b2y","c z"]

# toBase
10 2 toBase -> [1,0,1,0]
10 1,2,3 baseFrom -> 123
6_ 2 toBase -> [-1,-1,0]
6 2_ toBase -> [-1,-1,-1,0]

# digits
0 digits -> [0]
12 digits -> [1,2]
103_ digits -> [-1,0,-3]

# abs
5 negate abs -> 5
5 abs -> 5

# inc/etc
5 ) -> 6
'a ) -> 'b'
5 ( -> 4
'b ( -> 'a'

wholes 4 take -> [0,1,2,3]
4 countTo -> [1,2,3,4]

# reshape
"" 0jt reshape -> []
"a" 0jt reshape -> []
"" 0,1 reshape -> [""]
"a" 0,1 reshape -> ["","a"]
"abcdefg" 2 reshape -> ["ab","cd","ef","g"]
"abcdefg" 2,1,2,0,1 reshape -> ["ab","c","de","","f"]
"abcdefg" 2 2_a 1a reshape -> ["ab","","c"]
"abc" 1,1,1,0,0 reshape -> ["a","b","c","",""]
"abc" 4,0,0 reshape -> ["abc"]

# last
"asdf" last -> 'f'
1, tail last -> 0

# 'concat
"asdf","12" concat -> "asdf12"

# setdiff
"abcad" "babc" setDiff -> "ad"

# takeWhile
"123 456" dup takeWhile -> "123"

# min max
1 2 min -> 1
"ab" "aa" min -> "aa"

1 2 max ->2
"ab" "aa" max -> "ab"

# inits
Expand "abc" cons > reverse -> ["a","ab","abc"]

# coercion
123 "abc" cons -> ["a123","b123","c123"]
"abc" 123 cons -> ["1abc","2abc","3abc"]
1,2,3 " "* -> "1 2 3"
123 j "abc" cons -> ["a123"]

# promotes
"a b" '  split -> ["a","b"]
"abc" " " join -> "a b c"
"a" 'a =, -> 1
1 2 cons -> [2,1]

# special promotes
"asdf" "b" join -> "absbdbf"
123 "b" join -> "1b2b3"
"az","bx" 2,1 SortBy -> ["bx","az"]
"az","bx" 2,1 sortBy, -> ["bx","az"]
"abc" 3 sortBy -> RANK ERROR
"1" 1 0 IfElse -> 1
"" 1 0 ifElse, -> 0

# no promotes
4 head -> 1:3 (head) arg 1 rank too low and op does not promote (see https://golfscript.com/iogii/nittygritty.html#promotion )
5j Head -> RANK ERROR
5j Head, -> RANK ERROR
5 Head, -> RANK ERROR
5 N -> RANK ERROR
5 N, -> RANK ERROR
5 u -> 2
5 U -> RANK ERROR
5 u, -> 1:3 (u, concat) extra , used
5 U, -> RANK ERROR
'a "b" join -> RANK ERROR

#'
4, Head -> RANK ERROR
1 foldr head -> 1:3 (foldr superpad) arg 1 rank too low and op does not promote (see https://golfscript.com/iogii/nittygritty.html#promotion )

# low rank overloads

# base
5 2 D -> [1,0,1]
5 2,3 W -> 13
5 2,3 D -> [[1,0,1],[1,2]]

# backwards / countFrom
2B -> [2,3,...
1,2B 3 take -> [[1,2,3],[2,3,4]]
2,2B, -> 1:4 (B, reverse) extra , used
1,2,,3,4B -> [[3,4],[1,2]]
1,2,,3,4B, -> [[[1,2,3...

# T rangeTo / tail (same type sigs as ?, but it is alphanumeric)
2T -> [0,1]
2,2T -> [[0,1],[0,1]]
# 2,2T, -> RANK ERROR
2,2,,2,2T -> [[2,2]]
2,2,,2,2,,,3T, -> [[[3]]]

# U undigits / unite
12,34U -> 1234
12,34,,5U -> [1234,5]
12,34,,5U, -> 1:9 (U, concat) extra , used
12,34,,5,,,6,,7U -> [[12,34],[5],[6],[7]]
12,34,,5,,,6,,7U, -> [[1234,5],[6,7]]

# p digits / pivot
12p -> [1,2]
12,34p -> [[1,2],[3,4]]
12,34,,5p -> [[12,5],[34]]
12,34,,5p, -> [[[1,2],[3,4]],[[5]]]

# A min / append
1 2 A -> 1
"abzc" 'd A -> "abdc"
#'
"az","19" "bx","28" A -> ["az","19","bx","28"]
"az","19" "bx","28" A, -> ["ax","18"]
# "az","19" "bx","28" A,, -> RANK ERROR

# Test promote rather than zip low rank overload
"abzc"J "d" A -> ["abzc","d"]
"d" "abzc"J A -> ["d","abzc"]

"abzc"J "d" A, -> ["a"]

1,2 2,1 A -> [1,1]
1,2 2,1 A, -> 1:9 (A, append) extra , used
# 1,2J 2,1J A, -> [1,2]
1jj 2jj A -> [[1],[2]]
1j 2jj A -> [[1],[2]]

1jj 2jj A, -> [[1]]

# X max / exclude (same type sigs as A)

# H pow10 / head
2H -> 100
1,2H -> [10,100]
1,2,,3,4H -> [1,2]
1,,2H, -> [[10],[100]]

# P Pivot / product
2,3P -> 6
2,3,,4P -> [6,4]
2,3,,4,5,,,5P -> [[[2,3],[5]],[[4,5]]]
2,3,,,4P, -> [[6],[4]]

# K take / kCopy
1 3 K -> [1,1,1]
1,2 3 K -> [[1,1,1],[2,2,2]]
1,2,,3,,4 2 K -> [[1,2],[3]]
1,2,,3,,4 2 K, -> [[[1,1],[2,2]],[[3,3]],[[4,4]]]

# D digitize / drop
10 2 D -> [1,0,1,0]
10,11 2 D -> [[1,0,1,0],[1,0,1,1]]
10,11,,12 2 D -> []
10,11,,12 2 D, -> [[[1,0,1,0],[1,0,1,1]],[[1,1,0,0]]]

# W baseWas / while
5 3,4 W -> 19
5,4 3,4 W -> [19,16]
5,4,,3 3,4 W -> [[5,4],[3]]
5,4,,3 3,4 W, -> [[19,16],[13]]

# Fuzz test findings
# registered proc
# @OI!=M+M -> 1:3 (I cons) cannot construct the infinite type
