# 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
5;2+ -> 7 5
i) -> [777,778,...
$i) -> [777,778,...
del i) -> [777,778,...

# y1; -> 1 todo

# test rotate
+ * - "hi" "there" "moo" "bah" "fah" "boo") 100( 10 1 -> -7681 "hi" "there" "moo" "bah" "fah" "cpp"
a a a a a 1 -> [777,777,777,777,1,777]

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

# Test data parse
1, -> [1]
1,2, -> [1,2]
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 -> ERROR: found ", ," invalid data format
1,2,3~,4 -> [1,2,-3,4]
1,2,3~~,4 -> ERROR: 1:7 (~, negate) extra , used
1,2~ -> [-1,-2]
1,2~, -> [1,-2]
1~,"a" -> ["-1","a"]

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

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

# Test comments
"abcd"2# 0 -> "abcd" 2
"abcd"2#0 -> ["ab","cd"] 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-, -> ERROR: 1:4 (-, sub) extra , used

# Test empty program
->

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

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

'd 'a sub -> ERROR: 1:7 (sub) op is not defined for base types: char char

# 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
4 5 peek -> 4 5 4
4 5 mpeek 3+ -> 7 5 4

e 1 peek ++ -> [1,3,7,15...
e 1 mpeek ) ++ -> [2,6,14...

# wrapping before dupped value
+ 7 : -> 784 7
+ 7 mdup ) -> 784 8
+ 7 3 peek -> 784 7 3
+ 7 3 mpeek ) -> 784 8 3

a a 7 3 peek -> [3,7,777] 7
a a 7 3 mpeek ) -> [3,7,777] 8

# multiple dups and wrapped (could mess up token finding)
+ 7 : 50 : -> 827 7 7 50

# wrap at set/let
;let| -> ERROR: 1:1 (;) unterminated function

# wrapping inside fn
+e -> [777,1554,...
+5; -> ERROR: 1:3 (;) unterminated function
a a 5; -> [5,777,5]
a a 3 5! -> ERROR: 1:8 (!) unterminated function
a a a 3 5! -> [3,777,5,3]

# wrapping circular
# todo
# +: -> ERROR: 1:1 (+ add) op is not defined for base types: empty int
# +] -> ERROR: 1:1 (+ add) op is not defined for base types: empty int

# mdup op used in loop op
4;f 1,2,3+ -> ERROR: 1:3 (f) unterminated function

# dup2
3 4 peek mpeek a c -> [3,4] [4,3]

$ -> 777

# implicit
4>>+ -> ERROR: 1:3 (>) implicit value set twice
4> -> ERROR: implicit value set but not used
2*;- -> 0
1;2 -> ERROR: 1:2 (;) unterminated function

# outer use
100 7 mdup * + -> 707
100 0 foldr 1,2,3,4++ > -> 410
100 0 foldr 1,2,3,4++1> -> ERROR: implicit value set but not used
3 i 5 + 7 i 4 + + > 4k -> [3,15,31,51]
3 i 5 + 7 i 4 + + >, 4k -> [7,14,26,43]

# Test vars
4set xyz xyz+ -> 8
4set 3 3+ -> 8
3set+ + -> 3 3
3 1 cons set 3 5 take -> [1,1,1,1,1]
4set set -> ERROR: 1:2 (set) an id must follow `set`

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

# Test auto vars
5= A + -> 10
1,2j= B C -> [[2],[1]] [[1],[2]]
1,2j= B H I -> [2] [[1],[2]]
1,2j= B H J 0I>del -> [2] [[1],[2]]
1,2j= B T C -> [[1]] [[1],[2]]

1,2= -> ERROR: 1:4 (=) Sets register 'A' but it is never used
1,2== -> ERROR: 1:4 (=) Sets register 'A' but it is never used
1,2j= B ==== -> ERROR: 1:9 (=) Sets register 'C' but it is never used
A D G J L N P S U WXYZ======== -> ERROR: 1:27 (=) Out of letters for auto vars

# 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
del ->

# Test set / set next at end
A+-2=1 -> -778 2
+b 5 set b -> 782 5

# Test let
a 4 5 let a -> 5 4
let a a -> 777

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

# Test empty type
nil head just len -> 1
nil head -> 0
nil Not -> 1
nil O -> [[]]

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

# Test that empty type cannot be applied to concrete things even x
nil ) -> []
nil abs -> []

nil 1+ -> []

# this could be tail or rangeTo but should be tail since that doesn't type default
nil T -> []

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

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

# Test empty block
e> -> [0,0,...

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

# complex coerce
1,2,,3,4 "c" 1,"2" Y -> ["c","c"]

# test infinite type
nil meld cons -> ERROR: 1:10 (cons) cannot construct the infinite type
# inner push/pop
0 iterate = 1+ > 5 keep A 6 keep -> [0,1,2,3,4] [0,1,2,3,4,5]
0 iterate set 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]

# doesn't implicitly end after only a unary op
m )1,2,3+) -> 10
m 1,2,3+) -> 7
m 1,2,3+ -> 6
m )1,2,3+ -> 9
m ) -> ERROR: 1:1 (m) unterminated function

# 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 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]],[],[]]

1,1 iterate : t + -> [1,1,2,3,5...
0 iterate = 1,2,,4,5 + > del L 5 K -> [[0,1,3],[0,4,9],[],[],[]]
0 iterate = 1,2,,4,5,,,6 + > del L 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

# 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 -> ERROR: 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
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 charSubtraction -> 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"

"aA_1 " charClass len -> 96
'0 charClass -> "0123456789"
256 '\0 + charClass -> ""

"abcd" "f" dropUntilAfterSubstring -> ""
"abcd" "f" getSubstring -> ""
"abcd" "f" keepUntilSubstring -> "abcd"

"ff" 1 rightJustify -> "ff"

# 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"
5 3 take -> [5,5,5]
5 3 Take ->[[5],[5],[5]]

# 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"

# 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","cd"]
"abcd" 0,1 chunkWhen -> ["a","bcd"]
"" 0,1 chunkWhen -> [""]
"abc" nil chunkWhen -> ["abc"]
"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 Q -> 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 -> ERROR: 1:3 (head) arg 1 rank too low and op does not promote (see https://golfscript.com/iogii/types.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, -> ERROR: 1:3 (u, concat) extra , used
5 U, -> RANK ERROR
'a "b" join -> RANK ERROR

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

# low rank overloads

# base
5 2 D -> [1,0,1]
5 2,3 # -> 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, -> ERROR: 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, -> ERROR: 1:4 (T, tail) extra , used
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, -> ERROR: 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 / transpose
12P -> [1,2]
12,34P -> [[1,2],[3,4]]
12,34,,5P -> [[[1,2],[3,4]],[[5]]]
12,34,,5,,,7P -> [[[12,34],[7]],[[5]]]
12,34,,5,,,7P, -> [[[[1,2],[3,4]],[[5]]],[[[7]]]]

# A min / append
1 2 (, -> 1
1j 2j ((, -> [1]

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

# 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]]

# 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 fromBase / reshape
5 3,4 #-> 19
5 3,4 #,-> ERROR: 1:7 (#, reshape) extra , used
5,4 3,4 #-> [[5,4]]
5,4 3,4 #, -> [19,16]

# Test ab type
"abc" 1 filter -> "a"
'a 1 filter -> "a"
'a 0,1 filter -> ""
"abc" 0,1,1 filter -> "bc"
"abc","def" 0,1,1 filter -> ["bc","ef"]
"abc" 0,1,1,,1,0 filter -> ["bc","a"]

0j 1 2 ifElse -> [2]
0j 1 2 IfElse -> 1
0 1j 2j ifElse -> [2]
0 1j 2j IfElse -> [2]

nil 1 2 ifElse -> []
nil 1 2 IfElse -> 2

# todo "abc" 1 Filter -> ERROR: 1:9 (Filter) arg ranks too low and Filter op cannot promote BOTH args, doing so would could create rank invariant violations
# ["abc"]
'a 1 Filter -> ERROR: 1:6 (Filter) arg ranks too low and Filter op cannot promote BOTH args, doing so would could create rank invariant violations

# ["a"]
'a 0,1 Filter -> ERROR: 1:8 (Filter) arg ranks too low and Filter op cannot promote BOTH args, doing so would could create rank invariant violations
# ["a"]
# todo "abc" 0,1,1 Filter -> ERROR: 1:13 (Filter) arg ranks too low and Filter op cannot promote BOTH args, doing so would could create rank invariant violations

# ["abc"]
"abc","def" 0,1,1 Filter -> ["def"]
"abc" 0,1,1,,1,0 Filter -> "ab"
"abc","def" 0,1,1,,1,0 Filter -> ["abc","def"]
"abc","def" 0,1,1,,1,0,,,1 Filter -> ["ab","d"]
"abc","def",,"xyz" 0,1,1,,1,0 Filter -> [["def"],["xyz"]]

# Test 3 arg ab type
1 'a "bc" ifElse -> "aa"
1 "xyz" "bc" ifElse -> "xy"
1,0 'a "bc" ifElse -> "ac"
1,0 "xyz" "bc" ifElse -> "xc"

1 'a "bc" IfElse -> "a"
1 "xyz" "bc" IfElse -> "xyz"
1,0 'a "bc" IfElse -> "a"
1,0 "xyz" "bc" IfElse -> "xyz"

0 "abc","def",,"jkl","mno" 'z IfElse -> [["z","z"],["z","z"]]
1,0 "abc","def",,"jkl","mno" 'z IfElse -> [["abc","def"],["z","z"]]
1,0 "abc","def",,"jkl","mno" "xyz" IfElse -> [["abc","def"],["xyz","xyz"]]

# Test broadcast on non scalar op
"a","b",,"x","y" "12","34" a -> [["a12","b12"],["x34","y34"]]

# this can cause problems with ghc
nil dup indices -> []

a set a -> ERROR: 1:1 (a) direct circular dependency

negate input -> -777 777

nil, transpose ; type -> "[[int]]" []

# stress test haskell empty type annotations
nil nil max : type -> [] "[]"

# direct circular dependency only in ir2
a superpad set a -> ERROR: direct circular dependency
