diff --git a/.gitignore b/.gitignore index 279075cb..e281b660 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ cbqn-jit.bqn /test/ffi/shared.got /test/ffi/sharedTest /test/ffi/lib.so +/test/testDir/ # other /local/ diff --git a/test/README.md b/test/README.md index 186e67f1..0658a787 100644 --- a/test/README.md +++ b/test/README.md @@ -6,6 +6,7 @@ Must be run from the projects root directory. test/mainCfgs.sh path/to/mlochbaum/BQN // run the test suite for a couple primary configurations test/x86Cfgs.sh path/to/mlochbaum/BQN // run the test suite for x86-64-specific configurations, including singeli; 32-bit build is "supposed" to fail one test involving ⋆⁼ test/moreCfgs.sh path/to/mlochbaum/BQN // run "2+2" in a bunch of configurations; requires dzaima/BQN to be accessible as dbqn +test/run.bqn // run tests in test/cases/ ./BQN test/cmp.bqn // fuzz-test scalar comparison functions =≠<≤>≥ ./BQN test/equal.bqn // fuzz-test 𝕨≡𝕩 ./BQN test/copy.bqn // fuzz-test creating new arrays with elements copied from another @@ -23,4 +24,25 @@ make -C test/ffi // test FFI functionality; expects both regular and shared libr legacy utilities: test/readTests.bqn // read mlochbaum/BQN tests in various formats test/precompiled.bqn // run a precompiled expression +``` + +Format of tests in `test/cases/`: +```python +%DEF somename some code # add a definition to be used by later tests or other %DEFs +%USE somename # copy-paste in the code of the given definition to here +tests: + code that runs some !assertions # if there are no '!'s, 'lint' will complain + !"error message" % erroring code # can be written as "!% erroring code" at first, and let 'update-messages' insert the message + code %% expected value + ( + multiline + code + running !assertions + # the '(' and ')' lines must have no other characters in them + ) + +# flags addable anywhere in code: + %SLOW # enable only if 'slow' argument present + %NDEBUG # disable if 'debug' argument present + %NHEAPVERIFY # disable if 'heapverify' argument present ``` \ No newline at end of file diff --git a/test/cases/cells.bqn b/test/cases/cells.bqn new file mode 100644 index 00000000..c80db8d4 --- /dev/null +++ b/test/cases/cells.bqn @@ -0,0 +1,31 @@ +%DEF k _k ← {𝔽○•internal.Keep} +%DEF tcc %USE k ⋄ _tcc ← { ! ∧´ (<𝕨 𝔽_k˘⎊'e' 𝕩) ≡¨ (𝕨 𝔽˘⎊'e'•internal.Variation⟜𝕩)¨ "i"•internal.ListVariations 𝕩} + +•internal.Type¨ {𝕩-˜𝕩+2‿3⥊'¯'}¨ 0‿100‿100000 %% "c8arr"‿"c16arr"‿"c32arr" # assumed by test/cells.bqn + +1‿2 1⎉0 1 %% 1‿1 +1 1⎉0 1‿2 %% 1‿1 +! 20‿1200≡≢⥊˘a←20‿30‿40⥊↕24 ⋄ ! 20‿30‿40 ≡ ≢a +! (2⊸-⎉1 ≡ {2-𝕩}⎉1) 10‿10⥊↕100 +! (-⟜2⎉1 ≡ {𝕩-2}⎉1) 10‿10⥊↕100 +%USE k ⋄ n←1 ⋄ ≠{𝕊: (•Repr a) ! (≡⎉n ≡ ≡_k⎉n)´ a←(⊏⟜(3‿2‿2⥊'a'+↕26))¨ <˘ 2‿2‿2‿2•rand.Range 3}¨ ↕1000 +%USE k ⋄ n←2 ⋄ ≠{𝕊: (•Repr a) ! (≡⎉n ≡ ≡_k⎉n)´ a←(⊏⟜(3‿2‿2⥊'a'+↕26))¨ <˘ 2‿2‿2‿2•rand.Range 3}¨ ↕1000 +%USE k ⋄ n←3 ⋄ ≠{𝕊: (•Repr a) ! (≡⎉n ≡ ≡_k⎉n)´ a←(⊏⟜(3‿2‿2⥊'a'+↕26))¨ <˘ 2‿2‿2‿2•rand.Range 3}¨ ↕1000 +≠{𝕊k: ! (3⊸↑⎉k ≡ {3↑𝕩}⎉k) 2‿2‿2‿2⥊↕16}¨ ¯2+↕10 +≠{𝕊k: ! (1⊸↓⎉k ≡ {1↓𝕩}⎉k) 3‿3‿3‿3⥊↕81}¨ ¯2+↕10 + +!"˘: Result rank too large" % (0∾254⥊2)⊸⥊∘1˘ 0‿2⥊1 +!"⎉: Result rank too large" % (0∾254⥊2)⊸⥊∘1⎉¯1 0‿2⥊1 +!"⎉: Result rank too large" % (1⥊˜ 0∾204⥊2)⎉50 1⥊˜ 0∾100⥊2 +!"⎉: Result rank too large (204 ≡ =𝕩, 200 ≡ =𝔽v)" % {𝕊:(200⥊1)⥊1}⎉1 (205⥊1)⥊1 + +!"⎉: Argument frames don't agree (⟨3⟩ ≡ ≢𝕨, ⟨2⟩ ≡ ≢𝕩, common frame of 1 axes)" % "abc" ⊢⎉0 "ab" +!"˘: Argument frames don't agree (⟨3⟩ ≡ ≢𝕨, ⟨2⟩ ≡ ≢𝕩, common frame of 1 axes)" % "abc" ⊢˘ "ab" +! ∧´{𝕊: ! (∾≡{𝕨∾𝕩}´) (<•rand.Range∘≠⊸⊑ ⟨"ab",1‿2,⟨⟩,↕0,""⟩) ∾˜ (4•rand.Range≠)⊸⊏ ⟨1, {⇐}, 'a', <'a', <{⇐}, "ab", ↕0, ""⟩}¨↕10000 + +%USE tcc ⋄ ⟨2, 20, ¯2, ¯20, 0⟩ {𝕨 ↑_tcc 𝕩 ⋄ 𝕨 ↓_tcc 𝕩}⌜ ⟨<4, ↕5, 4‿5⥊↕20, 4‿5‿6⥊↕120⟩ +%USE tcc ⋄ ⟨<, ≍, ⊏, ⥊⟩ {𝕎 _tcc 𝕩}⌜ ⟨<4, ↕5, 4‿5⥊↕20, 4‿5‿6⥊↕120, 2‿3‿4‿5⥊↕120⟩ +%USE tcc ⋄ ⟨<, ≍, ⥊⟩ {𝕎 _tcc 𝕩}⌜ ⟨<4, ↕5, 4‿5⥊↕20, 4‿5‿6⥊↕120, 2‿3‿4‿5⥊↕120⟩ +%USE tcc ⋄ ⟨⊏⟩ {𝕎 _tcc 𝕩}⌜ ⟨4‿5⥊↕20, 4‿5‿6⥊↕120, 2‿3‿4‿5⥊↕120⟩ +%USE tcc ⋄ ⊏_tcc 4‿2⥊↕8 ⋄ 1⊏_tcc 4‿2⥊↕8 ⋄ ⊏_tcc ↕4‿2 ⋄ 1⊏_tcc ↕4‿2 +%USE tcc ⋄ ⊑_tcc 4‿2⥊↕8 ⋄ 1⊑_tcc 4‿2⥊↕8 ⋄ ⊑_tcc ↕4‿2 ⋄ 1⊑_tcc ↕4‿2 diff --git a/test/cases/fills.bqn b/test/cases/fills.bqn new file mode 100644 index 00000000..f23afc5c --- /dev/null +++ b/test/cases/fills.bqn @@ -0,0 +1,20 @@ +%DEF fill Fill←•internal.HasFill◶'e'‿{⊑1↑0⥊𝕩} + +%USE fill ⋄ F←⌊ ⋄ ⟨0,1,{⇐},+,@,'𝕩'⟩ Fill∘F⌜ ⟨⟨⟩, ↕0‿0, ↕0, 0‿2⥊↕0, "", 2‿0⥊""⟩ %NHEAPVERIFY %% 2‿4/[⟨'e',0‿0,0,0,'e','e'⟩,⟨'e','e','e','e','e','e'⟩] +%USE fill ⋄ F←+ ⋄ ⟨0,1,{⇐},+,@,'𝕩'⟩ Fill∘F⌜ ⟨⟨⟩, ↕0‿0, ↕0, 0‿2⥊↕0, "", 2‿0⥊""⟩ %NHEAPVERIFY %% 6‿6⥊⟨'e',0‿0,0,0,' ',' ','e',0‿0,0,0,' ',' ','e','e','e','e','e','e','e','e','e','e','e','e','e'," ",' ',' ','e','e','e'," ",' ',' ','e','e'⟩ +%USE fill ⋄ F←- ⋄ ⟨0,1,{⇐},+,@,'𝕩'⟩ Fill∘F⌜ ⟨⟨⟩, ↕0‿0, ↕0, 0‿2⥊↕0, "", 2‿0⥊""⟩ %NHEAPVERIFY %% 6‿6⥊⟨'e',0‿0,0,0,'e','e','e',0‿0,0,0,'e','e','e','e','e','e','e','e','e','e','e','e','e','e','e'," ",' ',' ',0,0,'e'," ",' ',' ',0,0⟩ +%USE fill ⋄ F←-˜ ⋄ ⟨0,1,{⇐},+,@,'𝕩'⟩ Fill∘F⌜ ⟨⟨⟩, ↕0‿0, ↕0, 0‿2⥊↕0, "", 2‿0⥊""⟩ %NHEAPVERIFY %% 6‿6⥊⟨'e',0‿0,0,0,' ',' ','e',0‿0,0,0,' ',' ','e','e','e','e','e','e','e','e','e','e','e','e','e','e','e','e',0,0,'e','e','e','e',0,0⟩ +%USE fill ⋄ (> !∘≡○Fill ⊢)¨ ⟨↕0, ""⟩ +%USE fill ⋄ ⟨⊢,Fill,Fill Fill⟩{𝕎𝕩}¨< 0⥊0‿1⊔2⥊<↕2 %% ⟨⟨⟩,⟨⟩,0‿0⟩ + +!¬•internal.HasFill <"hello"‿+ +%USE fill ⋄ fa ← Fill¨ a←⟨0, 2‿3‿4, 2‿0‿4, 0‿2‿3, 2⟩⥊⟜<⌜⟨0,'a',{⇐},1‿2⟩ ⋄ {𝕊f : fa {!𝕨≡Fill F 𝕩}¨ a}¨ ⟨⥊, 0⊸/, 0⊸⥊, 0⊸↑, 0⊸↓, ⊑∘⋈⟩ ⋄ fa %% 5/≍⟨0,' ','e',0‿0⟩ + +%USE fill ⋄ a←10⥊<1‿2 ⋄ { a∾↩𝕩⋄@}¨100⥊<<1‿2 ⋄ Fill a %% 0‿0 +%USE fill ⋄ a←10⥊<1‿2 ⋄ {a↩0↑a ⋄ a∾↩𝕩⋄@}¨100⥊<<1‿2 ⋄ Fill a %% 0‿0 +%USE fill ⋄ {𝕊: a←10⥊<1‿2 ⋄ { a∾↩𝕩⋄@}¨(𝕩⥊<<1‿2)∾<<1‿2‿3 ⋄ a!'e'≡Fill a}¨ ↕100 +%USE fill ⋄ {𝕊: a←10⥊<1‿2 ⋄ {a↩0↑a ⋄ a∾↩𝕩⋄@}¨(𝕩⥊<<1‿2)∾<<1‿2‿3 ⋄ a!'e'≡Fill a}¨ ↕100 + +# TODO: +# ⟨↑‿3⥊↕10 ⋄ ↑‿3⥊<¨↕10 ⋄ ↑‿3⥊<˘↕10⟩ +# 5‿¯5↑⌜⟨↕2 ⋄ "ab" ⋄ <¨↕2 ⋄ <˘↕2⟩ diff --git a/test/cases/fuzz.bqn b/test/cases/fuzz.bqn new file mode 100644 index 00000000..84004836 --- /dev/null +++ b/test/cases/fuzz.bqn @@ -0,0 +1,13 @@ +( + # character 𝕨∊𝕩 + ⟨V⇐Variation,LV⇐ListVariations,CL⇐ClearRefs,EE⇐EEqual⟩←•internal + R ← •rand.Range + _t←{w F _𝕣 x: ∧´EE¨⟜⊏⥊(LV 𝕨){(𝕨 V w) F 𝕩 V x}⌜LV𝕩?CL@; •Show¨𝕗‿𝕨‿𝕩⋄!0} + GS←{𝕊: @+0⌈(¯1+2⋆R∘≠⊸⊑7‿8‿15‿16‿20) - R˜R 200} + {𝕊:(GS@) ∊_t GS@}¨↕1000 +) + +( + # ∾𝕩 not getting garbage + ≠{𝕊: ! ∧´1=⥊∾⎊1 ⥊⟜1¨ (4•rand.Range 3) •rand.Range¨ 4}¨↕10000 +) diff --git a/test/cases/hash.bqn b/test/cases/hash.bqn new file mode 100644 index 00000000..e1d4c982 --- /dev/null +++ b/test/cases/hash.bqn @@ -0,0 +1,46 @@ +# some checks for behavior around ¯0; not strictly necessary to stay, but other tests will probably become meaningless without these! +1⊏64‿1•bit._cast ≍˘ •ParseFloat¨ "1.2"‿"-0" %% 63‿1/0‿1 +! (4⥊0) (≡ ∧ ≢○(64‿1•bit._cast⊢)) 1↓¯1×π∾4⥊0 +! ≢˝64‿1•bit._cast ≍˘0‿5⊏⥊(¯1⊸×≍⊢) (↕3)∾∞∾0÷0 + +# ¯0 +! ≡´ {•Hash •ParseFloat¨ 𝕩‿"1.2"}¨ "0"‿"-0" +! 1‿0 ≡ ∊{•ParseFloat¨ 𝕩‿"1.2"}¨ "0"‿"-0" +a←(•ParseFloat¨ "1.2"‿"-0"‿"0")∾-⊸⋈0÷0 ⋄ ∊1•Hash¨ a %% 1‿1‿0‿1‿0 +a←(•ParseFloat¨ "1.2"‿"-0"‿"0")∾-⊸⋈0÷0 ⋄ b←0+--a ⋄ ! a •internal.EEqual b ⋄ ! a ≡○(3⊸↑) b ⋄ ! 0≡a •Cmp b ⋄ ! a ≡○(1⊸•Hash¨) b ⋄ ! a ≡○(1⊸•Hash) b +a←(•ParseFloat¨ "1.2"‿"-0"‿"0")∾-⊸⋈0÷0 ⋄ ! (0‿3‿3‿3⊏a) ≡○•Hash (0‿4‿4‿4⊏a) + +# functions +⍷⟨⊢⊢⊢, ⊢⊢⊢, +⊢⊢, ⊢+⊢, ⊢⊢+, ⊢⊢, ⊢⊢, ⊢+, 1⊸+, 1⊸+, 2⊸+, 1⟜+, 1⊸×, ⊢+⊢, ⊢⊢⊢, +⊢⊢, +˘, ע, +˘, +˝⟩ %% ⟨⊢⊢⊢, +⊢⊢, ⊢+⊢, ⊢⊢+, ⊢⊢, ⊢+, 1⊸+, 2⊸+, 1⟜+, 1⊸×, +˘, ע, +˝⟩ + +# various +[1‿1, 0‿1, 1‿0, 0‿0, 1‿1, 0‿0] ∊ [0‿0, 0‿1, 1‿0] %% 0‿1‿1‿1‿0‿1 +[[0‿0, 0‿1, 1‿0, 1‿1], [1‿1, 0‿1, 1‿0, 0‿0]] ∊ [0‿0, 0‿1, 1‿0] %% 2‿4⥊1‿1‿1‿0‿0‿1‿1‿1 +[1‿1, 0‿1, 1‿0, 0‿0, 1‿1, 0‿0] ∊○(≍⎉0) [0‿0, 0‿1, 1‿0] %% 0‿1‿1‿1‿0‿1 +[[0‿0, 0‿1, 1‿0, 1‿1], [1‿1, 0‿1, 1‿0, 0‿0]] ∊○(≍⎉0) [0‿0, 0‿1, 1‿0] %% 2‿4⥊1‿1‿1‿0‿0‿1‿1‿1 +⊐˜∾˜"ihxtIddKLp"‿'r'‿÷‿"EXiRowcDXx"‿'a'‿"ZNtqFbDCYZ"‿⍒‿0.05369125494326554‿↑‿5 %% ∾˜↕10 +0‿1∊˜⟨"ab","cd"⟩ %% 0‿0 +0‿1⊐ ⟨"ab","cd"⟩ %% 2‿2 +(<"ab")∊"ab"‿"cd" %% <1 +(<"cd")∊"ab"‿"cd" %% <1 +(<"ef")∊"ab"‿"cd" %% <0 +(127⥊"abc")⊐"abcd" %% 0‿1‿2‿127 +(128⥊"abc")⊐"abcd" %% 0‿1‿2‿128 +(32767⥊"abc")⊐"abcd" %% 0‿1‿2‿32767 +(32768⥊"abc")⊐"abcd" %% 0‿1‿2‿32768 +(127⥊"abc")⊐100⥊"ababacadabacaba" %% (100⥊0‿1‿0‿1‿0‿2‿0‿ 127‿0‿1‿0‿2‿0‿1‿0) +(128⥊"abc")⊐100⥊"ababacadabacaba" %% (100⥊0‿1‿0‿1‿0‿2‿0‿ 128‿0‿1‿0‿2‿0‿1‿0) +(32767⥊"abc")⊐100⥊"ababacadabacaba" %% (100⥊0‿1‿0‿1‿0‿2‿0‿32767‿0‿1‿0‿2‿0‿1‿0) +(32768⥊"abc")⊐100⥊"ababacadabacaba" %% (100⥊0‿1‿0‿1‿0‿2‿0‿32768‿0‿1‿0‿2‿0‿1‿0) +⍷ •internal.Variation⟜(↕1)¨ "Ab"‿"Ai8" %% ⟨⋈0⟩ +!∘≡¨⟜⊏ 0•Hash¨ ⟨↕5 ⋄ 1↓0.5∾↕5 ⋄ 1↓'h'∾↕5⟩ + +{b←•internal.Unshare a←"Ai8"•internal.Variation ∾⟨16⥊0‿0‿0‿0‿0‿0‿0‿¯128, 8⥊0, 8↑2⟩ ⋄ c←8‿64•bit._cast a ⋄ ! 1‿0‿0‿1≡∊c ⋄ •internal.Keep •Hash c ⋄ ! a≡b} # make sure sign bit doesn't mutate away + +# error messages +!"∊: 𝕩 cannot have rank 0" % 1‿2‿3∊0 +!"⊐: 𝕨 cannot have rank 0" % 0⊐1‿2‿3 +!"⊒: 𝕨 cannot have rank 0" % 0⊒1‿2‿3 +!"∊: Rank of 𝕨 must be at least the cell rank of 𝕩 (⟨2⟩ ≡ ≢𝕨, 2‿2‿2 ≡ ≢𝕩)" % 1‿2∊2‿2‿2⥊1‿2 +!"⊐: Rank of 𝕩 must be at least the cell rank of 𝕨 (2‿2‿2 ≡ ≢𝕨, ⟨2⟩ ≡ ≢𝕩)" % (2‿2‿2⥊1‿2)⊐1‿2 +!"⊒: Rank of 𝕩 must be at least the cell rank of 𝕨 (2‿2‿2 ≡ ≢𝕨, ⟨2⟩ ≡ ≢𝕩)" % (2‿2‿2⥊1‿2)⊒1‿2 diff --git a/test/cases/patterns.bqn b/test/cases/patterns.bqn new file mode 100644 index 00000000..df6d57eb --- /dev/null +++ b/test/cases/patterns.bqn @@ -0,0 +1,53 @@ +%DEF k _k ← {𝔽○•internal.Keep} + +# weird "functions" +4 10´⟨⟩ %% 4 +4 10˝⟨⟩ %% 4 +4 10`⟨⟩ %% ⟨⟩ +4 10´↕0 %% 4 +4 10˝↕0 %% 4 +4 10`↕0 %% ↕0 +4 {˜}´↕0 %% 4 +4 {˜}˝↕0 %% 4 +4 {∘}`↕0 %% ↕0 +{∘}¨↕0 %% ⟨⟩ +{˜}¨˜↕0 %% ⟨⟩ +!"Calling a modifier" % 4 {˜}´↕1 +!"Calling a modifier" % 4 {˜}˝↕1 +!"Calling a modifier" % 4 {∘}`↕1 +!"Calling a modifier" % {∘}¨↕1 +!"Cannot call a modifier" % {˜}¨˜↕1 +4 {˜}˙´↕1 %% ˜ +4 {˜}˙˝↕1 %% ˜ +4 {∘}˙`↕1 %% ⟨∘⟩ +{∘}˙¨↕1 %% ⟨∘⟩ +{˜}˙¨˜↕1 %% ⟨˜⟩ +4 "ab"`↕4 %% 4⥊<"ab" +!"Calling a modifier" % {∘}⌜˜ ↕10 +{∘}˙⌜˜ ↕10 %% 10‿10⥊⟨∘⟩ +"ab"` "hello" %% 'h'∾4⥊<"ab" + +# ˝ plus ˘ +%USE k ⋄ (+˝˘ !∘≡ +˝_k˘) 1000000‿3•rand.Range 0 +%USE k ⋄ (-˜˝ !∘≡ -˜_k˝) 10 (•MakeRand 0).Range 1e5 +%USE k ⋄ (-˜˝˘ !∘≡ -˜_k˝˘) 3↕10 (•MakeRand 0).Range 1e5 + +# +` +%USE k ⋄ {𝕊: (+` !∘≡ +_k`) 1e3•rand.Range 0}¨↕1000 +%USE k ⋄ {𝕊: (•rand.Range 0) (+` !∘≡ +_k`) 1e3•rand.Range 0}¨↕1000 + +# <` +%USE k ⋄ (<` !∘≡ <_k`)¨ (1000⊸⥊)¨⊸∾ "Ab"⊸•internal.Variation¨ "111000"‿"1111000"‿"0111000"-'0' + +# ≠` +{𝕤⋄b←"Ab"•internal.Variation a←"Ai32"•internal.Variation 1000 •rand.Range 2 ⋄ ! (≠`a)≡≠`b}¨↕1000 +{𝕤⋄b←"Ab"•internal.Variation a←"Ai32"•internal.Variation 1000 •rand.Range 2 ⋄ ! (0≠`a)≡0≠`b}¨↕1000 +{𝕤⋄b←"Ab"•internal.Variation a←"Ai32"•internal.Variation 1000 •rand.Range 2 ⋄ ! (1≠`a)≡1≠`b}¨↕1000 + +# ∨´ & ∧´ +{n←𝕩 ⋄ ! (1+n) ≡ +´¬{∨´(-𝕩)↑1∾n↑0}¨↕400}¨↕200 # ∨´ with a single 1; %SLOW +{n←𝕩 ⋄ ! (1+n) ≡ +´¬ {¬∧´¬(-𝕩)↑1∾n↑0}¨↕400}¨↕200 # ∧´ with a single 1; %SLOW +{!¬ ∨´𝕩⥊0}¨↕1000 # ∨´ zeroes +{!¬ ∧´𝕩⥊0}¨1+↕1000 # ∧´ zeroes +{! ∨´𝕩⥊1}¨1+↕1000 # ∨´ ones +{! ∧´𝕩⥊1}¨↕1000 # ∧´ ones diff --git a/test/cases/prims.bqn b/test/cases/prims.bqn new file mode 100644 index 00000000..aadbf5f3 --- /dev/null +++ b/test/cases/prims.bqn @@ -0,0 +1,297 @@ +%DEF var V←•internal.Variation ⋄ LV←•internal.ListVariations +%DEF tvar %USE var ⋄ _tvar ← {F _𝕣 x: {F 𝕩 V x}¨ LV 𝕩; w F _𝕣 x: (LV 𝕨) {(𝕨 V w) F 𝕩 V x}⌜ LV 𝕩} +%DEF k _k ← {𝔽○•internal.Keep} + +# batch checks +{>0‿1‿3‿'a'‿{⇐} (≠𝕏`)⎊'e'⌜ ⟨10⥊0, 10⥊10, 10⥊1e4, 10⥊1e9, 10⥊1e20, "AAA", "⍉⍉⍉", "𝕨𝕨𝕨"⟩}¨ ⌊‿⌈‿+‿≠‿< %% ⟨5‿8⥊10‿10‿10‿10‿10‿'e'‿'e'‿'e'‿10‿10‿10‿10‿10‿'e'‿'e'‿'e'‿10‿10‿10‿10‿10‿'e'‿'e'‿'e'‿10‿10‿10‿10‿10‿'e'‿'e'‿'e'‿10‿10‿10‿10‿10‿'e'‿'e'‿'e',5‿8⥊10‿10‿10‿10‿10‿'e'‿'e'‿'e'‿10‿10‿10‿10‿10‿'e'‿'e'‿'e'‿10‿10‿10‿10‿10‿'e'‿'e'‿'e'‿10‿10‿10‿10‿10‿'e'‿'e'‿'e'‿10‿10‿10‿10‿10‿'e'‿'e'‿'e',5‿8⥊10‿10‿10‿10‿10‿'e'‿'e'‿'e'‿10‿10‿10‿10‿10‿'e'‿'e'‿'e'‿10‿10‿10‿10‿10‿'e'‿'e'‿'e'‿10‿10‿10‿'e'‿'e'‿'e'‿'e'‿'e'‿'e'‿'e'‿'e'‿'e'‿'e'‿'e'‿'e'‿'e',5‿8⥊10‿10‿10‿10‿10‿3‿3‿3‿10‿10‿10‿10‿10‿3‿3‿3‿10‿10‿10‿10‿10‿3‿3‿3‿10‿10‿10‿10‿10‿3‿3‿3‿10‿10‿10‿10‿10‿3‿3‿3,5‿8⥊10‿10‿10‿10‿10‿3‿3‿3‿10‿10‿10‿10‿10‿3‿3‿3‿10‿10‿10‿10‿10‿3‿3‿3‿10‿10‿10‿10‿10‿3‿3‿3‿'e'‿'e'‿'e'‿'e'‿'e'‿'e'‿'e'‿'e'⟩ + +# total array comparison +%USE k ⋄ a ← 0‿@‿'a'‿∞‿¯∞‿1‿¯1∾⍷∾{⟨𝕩⥊0, 𝕩⥊1, {1⌾((¯1¨≢𝕩)⊸⊑)𝕩}⍟(0≠×´∘≢) 𝕩⥊0⟩}¨ ∾{⥊(<⟨⟩)∾⌜´𝕩⥊<↕3}¨↕4 ⋄ r←(⊑(⍋-⍒)∘⋈)_k⌜˜ a ⋄ ! r ≡ •Cmp⌜˜a ⋄ r %% '1'-˜73‿73⥊"1000202002000002222000002000000222222222222200000200000022220000002000000210222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222001222222222222222222222222222222222222222222222222222222222222222222222000010000200000222200000200000022222222222220000020000002222000000200000020002122022020222222020222022022222222222222202022202202222220220222022020000201002000002222000002000000222222222222200000200000022220000002000000200020210200000222200000200000022222222222220000020000002222000000200000020002222122020222222020222022022222222222222202022202202222220220222022020000000001000000000000000000000000000000000000000000000000000000000000000200020220210000222200000200000022222222222220000020000002222000000200000020002222222120222222020222022022222222222222202022202202222220220222022022000202202201002222200002202000222222222222220000220200022222020002202000200022222222212222222202222220222222222222222220222222022222222202222220220002022022020122222020022022022222222222222202002202202222220220222022020000000002000001000000000000000000000000000000000000000000000000000000000000000000200000210200000200000020020020020020000020000002002000000200000000000000020000022120000020000002202202202202000002000000220200000020000000000000002000002001000000000000200000000200000000000000020000000000000000200020220220000222210000200000022222222222220000020000002222000000200000020002222222220222222120222022022222222222222202022202202222220220222022022000202202202002222201002202000222222222222220000220200022222020002202000200022222222222222222212222220222222222222222220222222022222222202222220220002022022020222222020122022022222222222222202002202202222220220222022020000000002000002002000001000000200200000200200000000000020020000000000000200020220220000222220000210000022222222222222000020000002222202000200000020002222222220222222220222122022222222222222222022202202222222220222022022000202202200002222200002201000222222222222220000220000022222020002202000200020220220200222220200220210022222222222222020022020002222202202220200020002222222222222222222222222122222222222222222222222202222222222222222022000202202202002222202002202201222222222222220200220220022222022022202202000000000200000200000000000000010000000000000000000000000000000000000000000000000020000022020000020000002102002002002000002000000200200000020000000000000002000002222000002000000221220220220200000200000022020000002000000000000000200000200200000000000020010000020000000000000002000000000000000000000000020000022020000020000002202102002202000002000000220200000020000000000000002000002222000002000000222221220222200000200000022220000002000000000000000200000200200000200000020020010020020000000000002002000000000000000000000020000022020000020000002202202102202000002000000220200000020000000000000002000002222000002000000222222221222200000200000022220000002000000000000000200000200000000000000020000000010000000000000000000000000000000000000000020000022020000020000002202002002102000002000000200200000020000000000000002000002222000002000000222220220221200000200000022020000002000000000000000200000200200000000000020020000020010000000000002000000000000000020002022022000022222000020000002222222222222100002000000222200000020000002000222222222022222222022202202222222222222221202220220222222022022202202200020220220200222220200220200022222222222222010022020002222202000220200020002222222222222222222222222022222222222222222122222202222222220222222022000202202202022222202022202202222222222222220201220220222222022022202202000000000200000200200000200000020020020020020000010000002002000000000000020002022022000022222000022000002222222222222200002100000222220200020000002000222222222022222222022222202222222222222222202221220222222222022202202200020220220000222220000220200022222222222222000022010002222202000220200020002022022020022222020022022002222222222222202002202100222220220222020002000222222222222222222222222222222222222222222222222221222222222222222202200020220220200222220200220220222222222222222020022022012222202202220220200000000020000020000000000000002000000002000000000000000100000000000000000000000002000002202000002000000220200200220200000200000021020000002000000000000000200000222200000200000022222022022220000020000002212000000200000000000000020000020020000000000002002000002002000000000000200100000000000002000202202200002222200002000000222222222222220000200000022221000002000000200022222222202222222202220220222222222222222220222022022222212202220220220002022022000022222000020000002222222222222200002000000222220100020000002000202202202002222202002202000222222222222220200220200022222021002202000200022222222222222222222222220222222222222222222222222022222222212222220220002022022020022222020022020002222222222222202002202000222220220122020000000000002000002002000002000000200200200200200000200000020020000001000000200020220220000222220000220000022222222222222000022000002222202000210000020002222222220222222220222222022222222222222222022222202222222220222122022000202202200002222200002200000222222222222220000220000022222020002201000200020220220200222220200220220022222222222222020022022002222202202220210020002222222222222222222222222222222222222222222222222222222222222222222122000202202202002222202002202200222222222222220200220220022222022022202201" +!"∧: Argument cannot have rank 0" % ∧@ +!"∨: Argument cannot have rank 0" % ∨@ +(=⋈≡)˜{⇐} %% 1‿1 +(≠⋈≢)˜{⇐} %% 0‿0 +{⇐}(=⋈≡){⇐} %% 0‿0 +{⇐}(≠⋈≢){⇐} %% 1‿1 + +# !𝕩 & 𝕨!𝕩 +!"Assertion error" % !0 +!"Assertion error" % !0 +!"foo" % !"foo" +!"foo" % "foo"!0 +!"foo" % "foo"!"bar" +!⎊•CurrentError 1‿+ %% ⟨1,+⟩ +!⟜0⎊•CurrentError 1‿+ %% ⟨1,+⟩ +!1 %% 1 +"foo"!1 %% 1 + + +# |𝕩 +{| (↕10)∾𝕩}¨ -2⋆7‿15‿31 %% ⟨0‿1‿2‿3‿4‿5‿6‿7‿8‿9‿128,0‿1‿2‿3‿4‿5‿6‿7‿8‿9‿32768,0‿1‿2‿3‿4‿5‿6‿7‿8‿9‿2147483648⟩ + +# arith +(<1)+ 1 %% <2 + 1 +<1 %% <2 +(<1)+<1 %% <2 +@-@ %% 0 +!"-: Invalid character" % @-1 +!"+: Unexpected argument types" % @+@ +!"×: Unexpected argument types" % @×@ +!"÷: Unexpected argument types" % @÷@ +!"⋆: Unexpected argument types" % @⋆@ +!"√: Unexpected argument types" % @√@ +!"⌊: Unexpected argument types" % @⌊@ +!"⌈: Unexpected argument types" % @⌈@ +!"|: Unexpected argument types" % @|@ +!"∧: Unexpected argument types" % @∧@ +!"∨: Unexpected argument types" % @∨@ +!"-: Unexpected argument types" % 0-@ +!"÷: Unexpected argument types" % 0÷@ +!"+: Argument must consist of numbers" % +@ +!"-: Argument contained non-number" % -@ +!"×: Argument contained non-number" % ×@ +!"÷: Argument contained non-number" % ÷@ +!"⋆: Argument contained non-number" % ⋆@ +!"√: Argument contained non-number" % √@ +!"⌊: Argument contained non-number" % ⌊@ +!"⌈: Argument contained non-number" % ⌈@ +!"|: Argument contained non-number" % |@ +!"¬: Argument contained non-number" % ¬@ +!"This function can't be called monadically" % ≤@ +!"This function can't be called monadically" % ≥@ + +# 𝕨/𝕩 +2‿3‿0‿1/4‿3⥊↕⋈12 %% ⋈¨6‿3⥊0‿1‿2‿0‿1‿2‿3‿4‿5‿3‿4‿5‿3‿4‿5‿9‿10‿11 +2‿3‿0‿1/↕4 %% 6⥊0‿0‿1‿1‿1‿3 +2‿3‿0‿1/↕⋈4 %% ⋈¨6⥊0‿0‿1‿1‿1‿3 +!"Didn't expect negative integer" % 2‿¯3/↕2 +!"/: Lengths of components of 𝕨 must match 𝕩 (3 ≠ 4)" % 1‿2‿3/4‿5‿6‿7 +!"Didn't expect negative integer" % (4/1000‿¯1000) / 8⥊1 +!"Didn't expect negative integer" % (4/1000‿¯1000) / 8⥊1 + +# /𝕩 +!"Didn't expect negative integer" % / 4/1000‿¯1000 +!"/: Argument must have rank 1 (3‿3 ≡ ≢𝕩)" % /↕3‿3 +!"/: Argument must have rank 1 (⟨⟩ ≡ ≢𝕩)" % /0 +! (//⁼)⊸≡8‿15‿25‿32‿90‿101‿155‿165‿584‿594‿894‿912‿1312‿1328‿1350‿1367‿1391‿1407‿1469‿1486‿1559‿1566‿1576‿1582‿1592‿1599‿1609‿1616‿1626‿1635‿4086‿4093‿4114‿4122‿4141‿4149‿4169‿4177 + +# 𝕨⊏𝕩 +•internal.ElType¨ {(100⥊↕2)⊏𝕨‿𝕩}⌜˜ ⟨0, 1, 2, 127, 128, 32767, 32768, ¯32767, ¯32768, ¯32769, ¯1+2⋆31, 2⋆31, @, @+1, @+255, @+256, @+1114111, {⇐}, 1‿2⟩ %% (8-(=⌜˜<⟜5)×8-⌈⌜˜) 0‿0‿1‿1‿2‿2‿3‿2‿2‿3‿3‿4‿5‿5‿5‿6‿7‿8‿8 +0‿0‿0 ⊏ 1‿3⥊↕10 %% 3‿3⥊0‿1‿2 +≢¨ ⟨(2‿0‿3‿4‿5⥊1)⊏9‿8‿0‿7⥊0 ⋄ ⟨⟩⊏0‿8‿0‿7⥊0 ⋄ (2‿3‿0‿4⥊1)⊏↕10⟩ %% ⟨2‿0‿3‿4‿5‿8‿0‿7,0‿8‿0‿7,2‿3‿0‿4⟩ +!"⊏: Indexing out-of-bounds" % ⊏˜(200⥊1)⥊1 +!"⊏: Indexing out-of-bounds (24∊𝕨, 4‿4≡≢𝕩)" % 1‿24⊏↕4‿4 +!"⊏: Indexing out-of-bounds (¯24∊𝕨, 4‿4≡≢𝕩)" % 1‿¯24⊏↕4‿4 +!"𝕨⊏𝕩: 𝕨 must be an array of numbers or list of such arrays" % (1‿¯26∾@)⊏@∾↕5 +!"⊏: Indexing out-of-bounds (¯26∊𝕨, ⟨5⟩≡≢𝕩)" % ¯26⊏↕5 +!"Expected integer" % ¯26.5⊏↕5 +!"⊏: Indexing out-of-bounds" % 1‿¯26⊏↕5 +!"⊏: Indexing out-of-bounds" % 1‿26⊏↕5 +!"Expected integer" % 0‿1.1‿2 ⊏ ↕10 +!"⊏: Indexing out-of-bounds (1∊𝕨, 1‿3≡≢𝕩)" % 0‿0‿1 ⊏ 1‿3⥊↕10000 +!"⊏: Indexing out-of-bounds (2∊𝕨, ⟨2⟩≡≢𝕩)" % (1+9=↕10)⊏⟨1‿2,3⟩ +a←↕2 ⋄ ! "e" ≡ (↕10){b←a‿a‿a‿a‿a‿a‿a‿a‿a‿a ⋄ 𝕨⊏⎊"e"𝕩}⟨1‿2,3‿4⟩ ⋄ ! 0‿1 ≡ a +%USE tvar ⋄ {!∘≡¨⟜⊏⥊ 1‿¯1 {t←•internal.ElType 𝕩 ⋄ r←𝕨⊏𝕩 ⋄ t≥•internal.ElType r ⋄ r}_tvar 𝕩}¨ ⟨↕2, ↕4, "hello", ⟨"ab", "cd", "ef"⟩, ↕⋈4⟩ + +# 𝕨⊑𝕩 +!"⊑: 𝕨 contained a non-integer" % ⟨0.1⟩⊑↕3 +!"⊑: 𝕨 contained a non-integer" % ⟨2⋆80⟩⊑↕3 +%USE tvar ⋄ !¨ 'e'= (≍1‿2) {⟨𝕨⟩⊑𝕩}⎊'e'_tvar ↕5‿5 +%USE tvar ⋄ !¨ 1‿2⊸≡¨ (1‿2) ⊑_tvar ↕5‿5 + +# comparison +w←1‿1⥊1 ⋄ x←1‿2⥊1 ⋄ {! (∾⟨•Repr𝕩,": Expected equal shape prefix (1‿1 ≡ ≢𝕨, 1‿2 ≡ ≢𝕩)"⟩) ≡ w 𝕏⎊(•CurrentError∘@) x}¨ =‿≠‿<‿>‿≤‿≥ +w←1‿1⥊1 ⋄ x←1‿2⥊1 ⋄ w‿x <¨↩ ⋄ {! (∾⟨•Repr𝕩,": Expected equal shape prefix (1‿1 ≡ ≢𝕨, 1‿2 ≡ ≢𝕩)"⟩) ≡ w 𝕏⎊(•CurrentError∘@) x}¨ =‿≠‿<‿>‿≤‿≥ +w←1‿1⥊1 ⋄ x←2⥊1 ⋄ {! (∾⟨•Repr𝕩,": Expected equal shape prefix (1‿1 ≡ ≢𝕨, ⟨2⟩ ≡ ≢𝕩)"⟩) ≡ w 𝕏⎊(•CurrentError∘@) x}¨ =‿≠‿<‿>‿≤‿≥ +w←1‿1⥊1 ⋄ x←2⥊1 ⋄ w‿x <¨↩ ⋄ {! (∾⟨•Repr𝕩,": Expected equal shape prefix (1‿1 ≡ ≢𝕨, ⟨2⟩ ≡ ≢𝕩)"⟩) ≡ w 𝕏⎊(•CurrentError∘@) x}¨ =‿≠‿<‿>‿≤‿≥ +!"Invalid comparison" % <˜{⇐} +!"Invalid comparison" % ≤˜{⇐} +!"Invalid comparison" % >˜{⇐} +!"Invalid comparison" % ≥˜{⇐} +{! 5 (𝕏 ≡ 𝕏⌾⋈) ↕10}¨ =‿≠‿<‿>‿≤‿≥ +{! (↕10) (𝕏 ≡ 𝕏⌾⋈) 5}¨ =‿≠‿<‿>‿≤‿≥ +{! (↕10) (𝕏 ≡ 𝕏⌾⋈) 4⌊↕10}¨ =‿≠‿<‿>‿≤‿≥ + +# >𝕩 +!">: Result rank too large (200 ≡ =𝕩, 205 ≡ =⊑𝕩)" % > (200⥊1)⥊<(205⥊1)⥊1 +!">: Incompatible element shapes (encountered shapes ⟨2⟩ and 4‿5)" % > ↕¨⟨2, 4‿5⟩ +!">: Incompatible element shapes (encountered shapes 2‿3 and ⟨4⟩)" % > ↕¨⟨2‿3, 4⟩ +!">: Incompatible element shapes (encountered shapes 2‿3 and 4‿5)" % > ↕¨⟨2‿3, 4‿5⟩ +!">: Incompatible element shapes (encountered shapes 2‿0 and 4‿5)" % > ↕¨⟨2‿0, 4‿5⟩ +!">: Incompatible element shapes (encountered shapes ⟨0⟩ and 4‿5)" % > ↕¨⟨0, 4‿5⟩ +!">: Incompatible element shapes (encountered shapes ⟨0⟩ and ⟨⟩)" % > ↕¨⟨0, ⟨⟩⟩ +!">: Incompatible element shapes (encountered shapes 2‿3 and ⟨⟩)" % > ↕¨⟨2‿3, ⟨⟩⟩ +!">: Incompatible element shapes (encountered shapes 4‿5 and 4‿6)" % ≢>2‿3⥊⟨4‿5⥊↕20,4‿6⥊↕1⟩ +!"∾: Item trailing shapes must be equal (contained arrays with shapes ⟨2⟩ and ⟨3⟩ and later higher-rank array)" % ∾⟨1‿1, 1‿1‿1, ⟨1⟩, 2‿2⥊1⟩ +!"∾: Item trailing shapes must be equal (contained arrays with shapes 1‿4 and ⟨0⟩)" % ∾⟨1‿4⥊"abcd",⟨⟩⟩ +>⟨<'a',1⟩ %% 'a'‿1 +>⟨1,2,<3,4,<<5⟩ %% ⟨1,2,3,4,<5⟩ +≢>0‿1⥊<2‿3⥊<"ab" %% ↕4 +{a←↕3 ⋄ !'e'≡>⎊'e' ⟨a, a, ↕2, a, a⟩ ⋄ ! 1≡•internal.Refc a} +{a←↕3 ⋄ > ⟨a, a, ↕3, a, a⟩ ⋄ ! 1≡•internal.Refc a} +{a←(200⥊1)⥊↕3 ⋄ ! 'e'≡>⎊'e' (200⥊1)⥊⟨a, a, ↕2, a, a⟩ ⋄ ! 1≡•internal.Refc a} +%USE var ⋄ a←2‿3⥊↕6 ⋄ b←2‿3⥊"abcdef" ⋄ !∘≡¨⟜⊏ ⥊ (LV a) {>1‿2‿1‿1⥊𝕨‿𝕩V¨a‿b}⌜ LV b +%USE var ⋄ a←b←2‿3⥊<<˘"abcd" ⋄ !∘≡¨⟜⊏ ⥊ (LV a) {>1‿2‿1‿1⥊𝕨‿𝕩V¨a‿b}⌜ LV b +%USE var ⋄ {a‿b: ! ∧´(⊏≡¨⊢)⥊ (LV a) {>1‿2‿1‿1⥊𝕨‿𝕩V¨a‿b}⌜ LV b}¨ ⟨2⥊<2‿3⥊<<˘"abcd" ⋄ ⟨2‿3⥊↕6,2‿3⥊"abcdef"⟩⟩ +%USE var ⋄ {a‿b: ! ∧´(⊏≡¨⊢)⥊ (LV a) {∾𝕨‿𝕩V¨a‿b}⌜ LV b}¨ ⟨2⥊<2‿3⥊<<˘"abcd" ⋄ ⟨2‿3⥊↕6,2‿3⥊"abcdef"⟩⟩ + +# <𝕩 +! ⊑∘<¨⊸≡ ∾⟜- ⥊(¯2+↕5)+⌜2⋆↕40 +! ⊑∘<¨⊸≡ @+⥊¯1‿0‿1+⌜2⋆↕20 +! ⊑∘<⊸≡ {⇐} + +# ⋈𝕩 +! ⊑∘⋈¨⊸≡ ∾⟜- ⥊(¯2+↕5)+⌜2⋆↕40 +! ⊑∘⋈¨⊸≡ @+⥊¯1‿0‿1+⌜2⋆↕20 +! ⊑∘⋈⊸≡ {⇐} + +# ∾𝕩 +∾⟨"ab", 12, "de"⟩ %% ⟨'a','b',12,'d','e'⟩ +!"∾: Item trailing shapes must be equal (contained arrays with shapes 3‿3 and 3‿4)" % ∾⟨↕3‿3,↕3‿4⟩ +!"∾: Item trailing shapes must be equal (contained arrays with shapes ⟨2⟩ and 3‿3)" % ∾⟨1‿2,↕3‿3⟩ + +# 𝕨∾𝕩 +!"∾: Lengths not matchable (⟨6⟩ ≡ ≢𝕨, 1‿1 ≡ ≢𝕩)" % ("abc"∾"def")∾≍"a" +!"∾: Lengths not matchable (⟨6⟩ ≡ ≢𝕨, 1‿1 ≡ ≢𝕩)" % (("abc")∾"def")∾1‿1⥊1 + +! (∘‿2⥊"abcdefgh") ≡ ["ab","cd"]∾["ef","gh"] +! (∘‿2⥊"abcdef") ≡ ["ab","cd"]∾"ef" +! (∘‿2⥊"abcdef") ≡ "ab"∾["cd","ef"] +! (∘‿2⥊"abcdefgh") ≡ (a←["ab","cd"])∾["ef","gh"] ⋄ •internal.Keep a +! (∘‿2⥊"abcdef") ≡ (a←["ab","cd"])∾"ef" ⋄ •internal.Keep a +! (∘‿2⥊"abcdef") ≡ "ab"∾a←["cd","ef"] ⋄ •internal.Keep a + +!"∾: Argument ranks must differ by 1 or less (0≡=𝕨, 2≡=𝕩)" % 1∾↕3‿3 +!"∾: Argument ranks must differ by 1 or less (1≡=𝕨, 3≡=𝕩)" % 1‿2∾↕3‿3‿3 +!"∾: Argument ranks must differ by 1 or less (3≡=𝕨, 1≡=𝕩)" % 1‿2∾˜↕3‿3‿3 +!"∾: Lengths not matchable (3‿4 ≡ ≢𝕨, 3‿3 ≡ ≢𝕩)" % (↕3‿4)∾↕3‿3 + +!"∾: Lengths not matchable (2‿2 ≡ ≢𝕨, 2‿3 ≡ ≢𝕩)" % ["ab","cd"]∾["efg","hjk"] +!"∾: Lengths not matchable (2‿2 ≡ ≢𝕨, ⟨3⟩ ≡ ≢𝕩)" % ["ab","cd"]∾"efg" +!"∾: Lengths not matchable (⟨3⟩ ≡ ≢𝕨, 2‿2 ≡ ≢𝕩)" % "abz"∾["cd","ef"] +!"∾: Lengths not matchable (2‿2 ≡ ≢𝕨, 2‿3 ≡ ≢𝕩)" % (a←["ab","cd"])∾["efg","hjk"] +!"∾: Lengths not matchable (2‿2 ≡ ≢𝕨, ⟨3⟩ ≡ ≢𝕩)" % (a←["ab","cd"])∾"efg" +!"∾: Lengths not matchable (⟨3⟩ ≡ ≢𝕨, 2‿2 ≡ ≢𝕩)" % "abz"∾a←["cd","ef"] + +# 𝕨≍𝕩 +!"≍: 𝕨 and 𝕩 must have equal shapes (3‿4 ≡ ≢𝕨, 3‿3 ≡ ≢𝕩)" % (↕3‿4)≍↕3‿3 +!"≍: 𝕨 and 𝕩 must have equal shapes (⟨3⟩ ≡ ≢𝕨, ⟨2⟩ ≡ ≢𝕩)" % 1‿2‿3≍1‿2 +!"≍: 𝕨 and 𝕩 must have equal shapes (⟨3⟩ ≡ ≢𝕨, ⟨⟩ ≡ ≢𝕩)" % 1‿2‿3≍1 +!"≍: Result rank too large" % ≍˜(255⥊1)⥊1 + +# ≍𝕩 +!"≍: Result rank too large (255≡=𝕩)" % ≍⍟256 1 + +# « & » +!"shift: Lengths not matchable (⟨2⟩ ≡ ≢𝕨, 3‿3 ≡ ≢𝕩)" % 1‿2»↕3‿3 +!"shift: =𝕨 must be =𝕩 or ¯1+=𝕩 (0≡=𝕨, 3≡=𝕩)" % 1»↕2‿2‿2 +!"shift: =𝕨 must be =𝕩 or ¯1+=𝕩 (2≡=𝕨, 1≡=𝕩)" % (↕2‿2)»1‿2 +!"shift: Lengths not matchable (⟨2⟩ ≡ ≢𝕨, 3‿3 ≡ ≢𝕩)" % 1‿2«↕3‿3 +!"shift: =𝕨 must be =𝕩 or ¯1+=𝕩 (0≡=𝕨, 3≡=𝕩)" % 1«↕2‿2‿2 +!"shift: =𝕨 must be =𝕩 or ¯1+=𝕩 (2≡=𝕨, 1≡=𝕩)" % (↕2‿2)«1‿2 +!"«: Argument cannot be a scalar" % «0 +!"»: Argument cannot be a scalar" % »<0 + +# ⍉𝕩 +%USE var ⋄ !∘≡¨⟜⊏ {⍉ 𝕩 V a}¨ LV a←2‿3‿4•rand.Range 2 +%USE var ⋄ !∘≡¨⟜⊏ {⍉ 𝕩 V a}¨ LV a←⋈¨ 2‿3‿4•rand.Range 2 +%USE var ⋄ !∘≡¨⟜⊏ {⍉ 𝕩 V a}¨ LV a←@+2‿3‿4•rand.Range 100 + +# ⌽𝕩 +%USE var ⋄ {{! 𝕩 ≡ ⌽"Ai8"V⌽𝕩} 𝕩•rand.Range 2}¨ ↕1000 + +# ↑𝕩 & ↓𝕩 +!"↑: Argument must have rank at least 1" % ↑0 +!"↓: Argument must have rank at least 1" % ↓<0 + +# ¨ + 1 {𝕊:1‿2}¨ 1 %% <1‿2 + 1 {𝕊:1‿2}¨<1 %% <1‿2 +(<1){𝕊:1‿2}¨ 1 %% <1‿2 +(<1){𝕊:1‿2}¨<1 %% <1‿2 + 1 1‿2¨ 1 %% <1‿2 + 1 1‿2¨<1 %% <1‿2 +(<1)1‿2¨ 1 %% <1‿2 +(<1)1‿2¨<1 %% <1‿2 +!"Mapping: Expected equal shape prefix (⟨2⟩ ≡ ≢𝕨, 4‿4 ≡ ≢𝕩)" % 1‿2+¨↕4‿4 +!"Mapping: Expected equal shape prefix (⟨2⟩ ≡ ≢𝕨, ⟨4⟩ ≡ ≢𝕩)" % 1‿2+¨↕4 +⊢¨ {a←𝕩 ⋄ ⥊𝕩} 2‿3⥊<"a" %% 6⥊<"a" +⊢¨ {a←𝕩 ⋄ 2‿3‿1⥊𝕩} 2‿3⥊<"a" %% 2‿3‿1⥊<"a" +⊢¨ {a←𝕩 ⋄ 2‿3‿1⥊𝕩} 6⥊<"a" %% 2‿3‿1⥊<"a" +⊢¨ {a←𝕩 ⋄ 2‿3⥊⥊𝕩} 2‿3⥊<"a" %% 2‿3⥊<"a" +⊢¨ 2‿3⥊<"a" %% 2‿3⥊<"a" + +# ⊔ +!"⊔: ≠𝕨 must be either ≠𝕩 or one bigger (2≡≠𝕨, 3≡≠𝕩)" % 0‿0⊔↕3 + +# ↕𝕩 +!"Expected non-negative integer" % ↕@ +!"Expected non-negative integer" % ↕"hi" +!"↕: Argument must be either an integer or integer list (had rank 2)" % ↕2‿2⥊1 +!"↕: Result rank too large (300≡≠𝕩)" % ↕300⥊1 + +# 𝕨↕𝕩 +!"↕: Length of 𝕨 must be at most rank of 𝕩" % 0↕0 +!"↕: Length of 𝕨 must be at most rank of 𝕩" % 0‿0↕3⥊1 +0‿0↕3‿3⥊1 %% 4‿4‿0‿0⥊0 +1↕↕2‿3 %% 2‿1‿3⥊↕2‿3 +0↕↕3 %% 4‿0⥊0 + +# ≡𝕩 +≡¨ ⟨⟨⟩, ↕0, ""⟩ %% 1‿1‿1 +≡↕0‿0‿0 %% 1 +≡⟨1,1‿2,1⟩ %% 2 +≡⋈⍟100 0 %% 100 +≡↕10 %% 1 +≡0 %% 0 + +# 𝕨⥊𝕩 +!"⥊: Result rank too large" % (0∾300⥊2)⥊0 + +# ⊐𝕩 +⊐ ∾⟜-0‿1.5 %% 0‿1‿0‿2 + +# 𝕨⊒𝕩 +1‿2‿2‿3‿3‿2‿2‿1⊒1‿8‿5‿5‿6‿2‿5‿3‿1‿5‿1‿2‿4‿3‿4‿3‿1‿5‿2‿3‿4‿1‿5‿2 %% 0‿8‿8‿8‿8‿1‿8‿3‿7‿8‿8‿2‿8‿4‿8‿8‿8‿8‿5‿8‿8‿8‿8‿6 + +# 𝕨⍋𝕩 +!"⍋: 𝕨 must be sorted" % a←-¨ ∧⋈¨ ↕10 ⋄ a⍋⋈¨↕10 + +# 𝕨|𝕩 +{x←2⥊𝕨|𝕩 ⋄ ! x •internal.EEqual 𝕨‿𝕨|𝕩‿𝕩 ⋄ ! x •internal.EEqual 𝕨|𝕩‿𝕩}⌜˜ ⍷∧∾⟜- ⟨π, ∞, 0÷0, 0.5, 0.1⟩∾(↕10)∾⥊(¯4+↕9)+⌜2⋆7‿8‿15‿31‿32 +( + # %SLOW + ⟨V⇐Variation, LV⇐ListVariations, CL⇐ClearRefs, EE⇐EEqual⟩←•internal + tests ← ⍷∧∾⟜- ⟨π, ∞, 0÷0, 0.5, 0.1⟩∾(↕10)∾⥊(¯4+↕9)+⌜2⋆7‿8‿15‿31‿32 + {w𝕊x: + wl‿xl←2⥊¨w‿x + w‿x ! ∧´(⊏EE¨⊢) ⥊ wl {⟨ w|(𝕩 V xl) ⋄ (𝕨 V wl)|x ⋄ (𝕨 V wl)|(𝕩 V xl) ⟩}⌜○LV xl + CL@ + }⌜˜ tests +) + + + + + +# ⍟ +%USE tvar ⋄ a←¯5+↕10 ⋄ !¨ (⋈¨ 5+↕10)⊸≡¨ {1⊸+⍟𝕩 ⋈10}_tvar a +%USE tvar ⋄ a←¯5+↕10 ⋄ !¨ (⋈¨ 5+↕10)⊸≡¨ {1+⍟𝕩 ⋈10}_tvar a +%USE tvar ⋄ a←¯5+↕10 ⋄ !¨ (⋈¨ 5+↕10)⊸≡¨ {1+⍟(𝕩{!𝕩≡⋈10 ⋄ 𝕗}) ⋈10}_tvar a + +# ˘ & ⎉ +≢ (1⥊˜ 0∾203⥊2)⎉50 1⥊˜ 0∾100⥊2 %% 1‿50‿1‿203/0‿2‿0‿2 +!"⎉: Result rank too large" % (1⥊˜ 0∾203⥊2)⎉49 1⥊˜ 0∾100⥊2 +!"˘: Result rank too large" % ((255⥊1)⥊1)˘ 1‿2 + +# ` +!"`: Shape of 𝕨 must match the cell of 𝕩 (2‿2 ≡ ≢𝕨, 3‿2‿3 ≡ ≢𝕩)" % (2‿2⥊1)+`↕3‿2‿3 +!"`: Shape of 𝕨 must match the cell of 𝕩 (2‿2 ≡ ≢𝕨, 3‿3‿2 ≡ ≢𝕩)" % (2‿2⥊1)+`↕3‿3‿2 +!"`: Shape of 𝕨 must match the cell of 𝕩 (⟨⟩ ≡ ≢𝕨, 3‿3 ≡ ≢𝕩)" % 2+`↕3‿3 + +# ´ +!"´: Argument must be a list (3‿3 ≡ ≢𝕩)" % +´↕3‿3 +!"´: 𝕩 must be a list (3‿3 ≡ ≢𝕩)" % 2+´↕3‿3 + +# ⌜ +!"⌜: Result rank too large (200≡=𝕨, 200≡=𝕩)" % +⌜˜(200⥊1)⥊1 diff --git a/test/cases/syntax.bqn b/test/cases/syntax.bqn new file mode 100644 index 00000000..0bbac538 --- /dev/null +++ b/test/cases/syntax.bqn @@ -0,0 +1,54 @@ +# body usage +a←"zero"‿"one" ⋄ !a≡a⊸{𝕩?1⊑𝕨;0⊑𝕨}¨0‿1 +!"No header matched argument" % { 𝕊a‿b: a+b ; d𝕊a‿b‿c: a+b+c} ↕⥊3 +!"No header matched argument" % {d𝕊a‿b: a+b ; 𝕊a‿b‿c: a+b+c} ↕⥊2 +{𝕊a‿b: a+b ; 𝕊a‿b‿c: a+b+c} ↕⥊2 %% ⟨1⟩ +{𝕊a‿b: a+b ; 𝕊a‿b‿c: a+b+c} ↕⥊3 %% ⟨3⟩ +{4=⊑𝕩? "four" ; "idk: "‿𝕩}4+↕3 %% "four" +{4=⊑𝕩? "four" ; "idk: "‿𝕩}3+↕3 %% "idk: "‿⟨3,4,5⟩ +{𝕩+↩1 ⋄ 4=⊑𝕩? 1‿𝕩 ; 2‿𝕩}3+↕3 %% ⟨1,4‿5‿6⟩ +{𝕩+↩1 ⋄ 4=⊑𝕩? 1‿𝕩 ; 2‿𝕩}4+↕3 %% ⟨2,4‿5‿6⟩ +{𝕩↩𝕩+1 ⋄ 4=⊑𝕩? 1‿𝕩 ; 2‿𝕩}3+↕3 %% ⟨1,4‿5‿6⟩ +{𝕩↩𝕩+1 ⋄ 4=⊑𝕩? 1‿𝕩 ; 2‿𝕩}4+↕3 %% ⟨2,4‿5‿6⟩ +{1?"abc" ; "def"} %% "abc" +{0?"abc" ; "def"} %% "def" +{123456 ⋄ 1‿{2} ⋄ ⟨1⟩ ⋄ 1‿{1+5}} %% 1‿6 + +# forks with funky tines +{(𝕩⊏⟨⋈ ⋄ "ab" ⋄ 9⟩) {f‿g‿h←𝕨 ⋄ T←F G H ⋄ ⟨T⋈𝕩 ⋄ (≍𝕩‿𝕩)T⋈𝕩⟩} ↕3}¨ ↕2‿2‿2 %% 2‿2‿2⥊⟨⟨⟨⟨⟨0‿1‿2⟩⟩,⟨⟨0‿1‿2⟩⟩⟩,⟨⟨1‿2⥊⟨0‿1‿2,0‿1‿2⟩,⟨0‿1‿2⟩⟩,⟨1‿2⥊⟨0‿1‿2,0‿1‿2⟩,⟨0‿1‿2⟩⟩⟩⟩,⟨⟨⟨⟨0‿1‿2⟩⟩,"ab"⟩,⟨⟨1‿2⥊⟨0‿1‿2,0‿1‿2⟩,⟨0‿1‿2⟩⟩,"ab"⟩⟩,⟨"ab","ab"⟩,⟨"ab","ab"⟩,⟨⟨"ab",⟨⟨0‿1‿2⟩⟩⟩,⟨"ab",⟨1‿2⥊⟨0‿1‿2,0‿1‿2⟩,⟨0‿1‿2⟩⟩⟩⟩,⟨⟨"ab","ab"⟩,⟨"ab","ab"⟩⟩,⟨"ab","ab"⟩,⟨"ab","ab"⟩⟩ + +# body inverses +!"No monadic undo header found for this block" % {𝕩}⁼ 1 +!"No dyadic F⁼ undo header found for this block" % 1 {𝕩}⁼ 1 +!"No dyadic F˜⁼ undo header found for this block" % 1 {𝕩}˜⁼ 1 +!"No monadic undo header found for this 1-modifier block" % +{𝔽𝕩}⁼ 1 +!"No dyadic F⁼ undo header found for this 1-modifier block" % 1 +{𝔽𝕩}⁼ 1 +!"No dyadic F˜⁼ undo header found for this 1-modifier block" % 1 +{𝔽𝕩}˜⁼ 1 +!"No monadic undo header found for this 2-modifier block" % +{𝔽𝔾𝕩}+⁼ 1 +!"No dyadic F⁼ undo header found for this 2-modifier block" % 1 +{𝔽𝔾𝕩}+⁼ 1 +!"No dyadic F˜⁼ undo header found for this 2-modifier block" % 1 +{𝔽𝔾𝕩}+˜⁼ 1 + +# assignment +!"Reading variable before its defined" % {a} ⋄ a←1 +!"↩: Reading variable that hasn't been set" % {a⊢↩↕10} ⋄ a←2 +!"↩: Updating variable that hasn't been set" % {a↩↕10} ⋄ a←2 +!"↩: Reading variable that hasn't been set" % {a (↕10)˙↩} ⋄ a←2 +!"Assignment: Mismatched shape for spread assignment" % a‿b←1 +!"Assignment: Mismatched shape for spread assignment" % a‿b←1‿2‿3 +!"Assignment: Mismatched shape for spread assignment" % ⟨a⟩←<1 +!"Assignment: Mismatched shape for spread assignment" % ⟨⟩←1 +!"Assignment: Mismatched shape for spread assignment" % ⟨⟩←⟨1⟩ +⟨⟩←⟨⟩ %% ⟨⟩ + +# namespaces +⟨a,b⟩←•BQN"{x⇐1‿2⋄a⇐3‿4⋄y←5‿6⋄b⇐7‿8}" ⋄ a‿b %% ⟨3‿4 ⋄ 7‿8⟩ + +# immediate modifiers +!"No key found" % X←1‿2{a⇐𝕗} ⋄ ⟨b⟩←x +X←1‿2{a⇐𝕗} ⋄ ⟨a⟩←x ⋄ +´a %% 3 +X←1‿2{a⇐𝕘-𝕗}3‿4 ⋄ ⟨a⟩←x ⋄ +´a %% 4 +⟨a⟩←1‿2{a⇐𝕩+𝕗+𝕘}3‿4 1 ⋄ a %% 5‿7 +⟨a⟩←1‿2{a⇐𝕩+𝕗} 1 ⋄ a %% 2‿3 + +# arguments +{x←𝕩⋄𝕩↩@⋄𝕩⋈x}-↕10 %% @⋈-↕10 diff --git a/test/cases/system.bqn b/test/cases/system.bqn new file mode 100644 index 00000000..9f3377bb --- /dev/null +++ b/test/cases/system.bqn @@ -0,0 +1,236 @@ +# not tested here: •Out •Show •Exit •term •GetLine •Cmp •CurrentError •FFI •internal.HeapDump •file.MapBytes + +%DEF var V←•internal.Variation ⋄ LV←•internal.ListVariations +%DEF tvar %USE var ⋄ _tvar ← {F _𝕣 x: {F 𝕩 V x}¨ LV 𝕩; w F _𝕣 x: (LV 𝕨) {(𝕨 V w) F 𝕩 V x}⌜ LV 𝕩} + +# standard system values + +# •BQN +%USE tvar ⋄ !∘≡⟜" "¨ •BQN _tvar "1↑""""" +⟨⟩ •BQN "Ah"•internal.Variation"1↑""""" %% " " + +# •ReBQN +f←•ReBQN {system⇐"all"} ⋄ F "•internal.Type ↕10" %% "i8arr" +!"Unknown system function •internal" % f←•ReBQN {system⇐"none"} ⋄ F "•internal.Type ↕10" +f←•ReBQN {system⇐⟨"range"‿↕ ⋄ "add"‿+ ⋄ "reverse"‿⌽⟩} ⋄ F "•Reverse ¯5 •Add •Range 10" %% 4-↕10 +f←•ReBQN{⇐} ⋄ F "Ah"•internal.Variation"1↑""""" %% " " + +# •primitives +!∧´2=•Type¨ ⊑¨•primitives +!¨ (•Type¨1⊑¨•primitives)∊3‿4‿5 + +# •state +6⊸↑⌾(1⊸⊑) •file.Name⌾⊑ •state %% ⟨"testDir","system",⟨"arg0",1⟩⟩ + +# •args +•args %% ⟨"arg0",1⟩ + +# •path & •file.path +•file.Name •path %% "testDir" +•file.Name •file.path %% "testDir" + +# •name +6↑•name %% "system" + +# •wdpath +! ∧´ 2=•Type¨ •wdpath + +# •ns +{abc⇐1 ⋄ dÊF⇐2}•ns.Get¨ ⟨"abc", "ABC", "abC", "abc___", "DêF", "__D__Ê__F__"⟩ %% 1‿1‿1‿1‿2‿2 +!"No field named ""abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþabcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþ𝕨𝕨⍉!0123456789"" found" % {abc⇐1 ⋄ dÊF⇐2}⊸•ns.Get "ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞabcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþ𝕨𝕨⍉!0123456789_" +{abc⇐1 ⋄ dÊF⇐2 ⋄ n10⇐3}•ns.Has¨ ⟨"abc", "ABC", "abC", "abc___", "DêF", "__D__Ê__F__", "àbc", "def", "", ↕0, "𝕨", "012", "n10", "n1_0"⟩ %% 1‿1‿1‿1‿1‿1‿0‿0‿0‿0‿0‿0‿1‿1 +∨´{⇐}•ns.Has¨↑"abc123AEWQE___àÀ𝕨𝕩" %% 0 +!"•ns.Has: 𝕩 must be a string" % {⇐}•ns.Has ≍"" +!"•ns.Has: 𝕩 must be a string" % {⇐}•ns.Has 1‿2 +!"•ns.Get: 𝕩 must be a string" % {⇐}•ns.Get ≍"" +!"•ns.Get: 𝕩 must be a string" % {⇐}•ns.Get 1‿2 +{m←𝕩 ⋄ ⟨{𝕩 ⋈ m•ns.Get 𝕩}¨ •ns.Keys m ⋄ {m•ns.Has⋈𝕩}¨ "abcABC"⟩}¨ ⟨{a⇐1⋄b⇐↕10} ⋄ {a⇐'a'⋄b←2‿3⋄cde⇐𝕩}"abc"⟩ %% ⟨⟨⟨⟨"a",1⟩,⟨"b",0‿1‿2‿3‿4‿5‿6‿7‿8‿9⟩⟩,1‿1‿0‿1‿1‿0⟩,⟨⟨⟨"a",'a'⟩,⟨"cde","abc"⟩⟩,1‿0‿0‿1‿0‿0⟩⟩ + + + +# files; tests are ordered! +{•file.Exists 𝕩? ⊑•SH⟨"rmdir", •file.At 𝕩⟩; 0} "testdirNested" %% 0 +•file.Remove⍟•file.Exists¨ "testfile.bqn"‿"testfile2.bqn"‿"testfile3B.bqn" ⋄ 1 %% 1 +•file.At "/a/b" %% "/a/b" +! (•file.At "a/b") ≡ •file.path •file.At "a/b" +"a/b" •file.At "c/d" %% "a/b/c/d" +"a/b/" •file.At "c/d" %% "a/b/c/d" +"a/b/" •file.At "c/d/" %% "a/b/c/d/" +"a/b/" •file.At "/c/d" %% "/c/d" +"a/b" •file.At "/c/d/" %% "/c/d/" +•file.Exists "/dev/file that doesn't exist" %% 0 +!"Couldn't read file ""/dev/file that doesn't exist""" % •FChars "/dev/file that doesn't exist" +! (•path∾"/") ≡ •file.Parent •file.At "hi" + +!"•file.Lines: 𝕩 must be a list" % "testfile.bqn" •FLines 2‿2⥊<"abcd" +!"•file.Lines: 𝕩 must be a list" % "testfile.bqn" •file.Lines <"abcd" +!"Expected character" % "testfile.bqn" •FChars ⋈"abcd" +!"•file.Chars: 𝕩 must be a list of characters" % "testfile.bqn" •FChars <'a' +!"Expected character" % "testfile.bqn" •FBytes ⋈"abcd" +!"•file.Bytes: 𝕩 must be a list" % "testfile.bqn" •file.Bytes <'a' +!"Path wasn't a list of characters" % 'a' •FChars "hi" +!"Path wasn't a list of characters" % (4‿2⥊"testfile.bqn") •file.Chars "hi" + +! {𝕩≡•file.Name 𝕩 •FChars "abc"∾(@+10)∾"def𝕩"}"testfile.bqn" +! {𝕩≡•file.Name 𝕩 •FBytes •ToUTF8 "abc"∾(@+10)∾"def𝕩"}"testfile2.bqn" +! {𝕩≡•file.Name 𝕩 •FLines "abc"‿"def𝕩"} "testfile3.bqn" +•file.Type "testfile.bqn" %% 'f' +•file.Type •file.path %% 'd' +!¨ 0≤{𝕏 "testfile.bqn"}¨ •file.Created‿•file.Accessed‿•file.Modified +•file.Size "testfile.bqn" %% 11 + +•FBytes¨ "testfile.bqn"‿"testfile2.bqn"‿"testfile3.bqn" +•FChars "testfile.bqn" %% "abc"∾(@+10)∾"def𝕩" +•FBytes "testfile.bqn" %% @+97‿98‿99‿10‿100‿101‿102‿240‿157‿149‿169 +•FLines "testfile.bqn" %% "abc"‿"def𝕩" + +"testfile3B.bqn" •file.Rename "testfile3.bqn" +•file.Exists¨ "testfile.bqn"‿"nontestfile.bqn"‿"testfile3.bqn"‿"testfile3B.bqn" %% 1‿0‿0‿1 +¯22↑•file.Createdir "testdirNested" %% "/testDir/testdirNested" +"testfile.bqn"‿"testfile2.bqn"‿"testfile3.bqn"‿"testfile3B.bqn"‿"testdirNested" ∊ •file.List "." %% 1‿1‿0‿1‿1 +"testfile.bqn"‿"testfile2.bqn"‿"testfile3.bqn"‿"testfile3B.bqn"‿"testdirNested" ∊ •file.List •file.path %% 1‿1‿0‿1‿1 + +•file.Remove "testfile.bqn" %% 1 +•file.Remove "testfile2.bqn" %% 1 +•file.Remove "testfile3B.bqn" %% 1 +"testfile.bqn"‿"testfile2.bqn"‿"testfile3B.bqn" ∊ •file.List "." %% 0‿0‿0 + + + +# •ParseFloat & •Repr +v←1 ⋄ ! •BQN∘•Repr⊸≡ ⟨+,1‿2,+¨,(+V)(V+V),2‿2⥊↕4⟩ +# v←1 ⋄ •BQN∘•Repr⊸≡ ⟨V V V, V V⟩ # TODO enable +64‿1•bit._cast •ParseFloat¨ "123.456000000000000"‿"123.45600000000002" %% "11101110011111011111100101011000111101001011101101111010000000100001111001111101111110010101100011110100101110110111101000000010"-'0' +! ∧´'e'=•ParseFloat⎊'e'¨ "-"‿"e2"‿"-e2"‿"."‿".e2"‿"123e"‿"123e-"‿"123e+" +•ParseFloat "0."∾(n⥊'0')∾"1234e"∾•Repr n←1000000 %% 0.1234 +•Repr∘•ParseFloat¨ ⟨"1.23516411460311636e-323", "1.23516411460311637e-323"⟩ %% ⟨"1e¯323","1.5e¯323"⟩ +•Repr∘•ParseFloat¨ ⟨"1.235164114603116360e-323", "1.235164114603116361e-323"⟩ %% ⟨"1e¯323","1e¯323"⟩ +•Repr∘•ParseFloat¨ ⟨"1.2351641146031163604e-323", "1.2351641146031163605e-323"⟩ %% ⟨"1e¯323","1e¯323"⟩ + +# •Fmt +•Fmt 123 %% "123" + +# •SH +•SH⟨"true"⟩ %% 0‿⟨⟩‿⟨⟩ +•SH⟨"false"⟩ %% 1‿⟨⟩‿⟨⟩ +{stdin⇐"𝕩"∾@+↕256} •SH⟨"cat"⟩ %% ⟨0, "𝕩"∾@+↕256, ""⟩ +{stdin⇐"𝕩"∾@+↕256 ⋄ raw⇐0} •SH⟨"cat"⟩ %% ⟨0, "𝕩"∾@+↕256, ""⟩ +{stdin⇐@+↕256 ⋄ raw⇐1} •SH⟨"cat"⟩ %% ⟨0, @+↕256, ""⟩ + +# •Type +•Type¨ ⟨"ab",'a'‿1,1,0÷0,'a',@+1114111,+,{𝕩},¨,{𝕗},∘,{𝔽𝕘},{⇐},•rand⟩ %% 0‿0‿1‿1‿2‿2‿3‿3‿4‿4‿5‿5‿6‿6 + +# •Glyph +•Glyph¨ ⟨+,¨,∘⟩ %% "+¨∘" + +# •Decompose +{! 0‿𝕩 ≡ •Decompose 𝕩}¨ ⟨+, ¨, ˝⟩ +{! 1‿𝕩 ≡ •Decompose 𝕩}¨ ⟨{𝕩}, {𝔽𝕘}⟩ +{! ¯1‿𝕩 ≡ •Decompose 𝕩}¨ ⟨1,'a',"ab"⟩ +•Decompose¨ ⟨+-×, -÷, +¨, 1∘+⟩ %% ⟨⟨3,+,-,×⟩,⟨2,-,÷⟩,⟨4,+,¨⟩,⟨5,1,∘,+⟩⟩ + +# •UnixTime +•Type •UnixTime ↕10 %% 1 + +# •MonoTime +! ≤´•MonoTime¨↕2 + +# •Delay +t0←•MonoTime@ ⋄ ! 0.1≤•Delay 0.1 ⋄ ! 0.1≤(•MonoTime@)-t0 + +# •_timed tested at perf.bqn + +# •math +! ∧´0=⌊|1e10×{(+´𝕩)-•math.Sum 𝕩}¨ ↑1000•rand.Range 0 +!"•math.Sum: Argument must be a list (⟨⟩ ≡ ≢𝕩)" % •math.Sum 2 +!"•math.Sum: Argument must be a list (2‿2 ≡ ≢𝕩)" % •math.Sum 2‿2⥊1 +!"•math.Sum: Argument elements must be numbers" % •math.Sum 1‿'a' + +! {(𝕩 •math.Atan2 0) ≡ 𝕩 •math.Atan2 •ParseFloat"-0"} (-≍⊢) ∞∾˜↕3 +! {(0 •math.Atan2 𝕩) ≡ (•ParseFloat"-0") •math.Atan2 𝕩} (-≍⊢) ∞∾˜↕3 +E←•internal.EEqual ⋄ a←(¯1⊸×≍⊢) (↕3)∾∞∾0÷0 ⋄ {𝕩!(a 𝕏 0)E a 𝕏 •ParseFloat"-0" ⋄ 𝕩!(0 𝕏 a)E(•ParseFloat"-0") 𝕏 a}¨ (⊢∾{𝕏¨}¨) ⟨+,-,×,÷,⋆,√,⌊,⌈,|,¬,∧,∨,<,>,≠,=,≤,≥, •math.Atan2,•math.Comb,•math.Hypot⟩ +E←•internal.EEqual ⋄ {! (𝕏 4⥊0) E 𝕏 1↓¯1×π∾4⥊0}¨ (⊢∾{𝕏¨}¨) ⟨+,-,×,÷,⋆,√,⌊,⌈,|,¬, •math.Sin,•math.Cos,•math.Tan,•math.Asin,•math.Acos,•math.Atan,•math.Sinh,•math.Cosh,•math.Tanh,•math.Asinh,•math.Acosh,•math.Atanh,•math.Cbrt,•math.Log2,•math.Log10,•math.Log1p,•math.Expm1,•math.Fact,•math.LogFact,•math.Erf,•math.ErfC⟩ + +{15 𝕏 10}¨ ⟨•math.GCD,•math.LCM⟩ %% 5‿30 +⌊1e5×{0.1 𝕏 0.2}¨ ⟨•math.Atan2,•math.Comb,•math.Hypot⟩ %% 110714‿96959‿22360 +⌊1e5×{=˜◶99‿⊢¨ 𝕏 0.1‿3}¨ ⟨•math.Acos,•math.Acosh,•math.Asin,•math.Asinh,•math.Atan,•math.Atanh,•math.Cbrt,•math.Cos,•math.Cosh,•math.Erf,•math.ErfC,•math.Expm1,•math.Fact,•math.Log10,•math.Log1p,•math.Log2,•math.LogFact,•math.Sin,•math.Sinh,•math.Tan,•math.Tanh⟩ %% ⟨147062‿9900000,9900000‿176274,10016‿9900000,9983‿181844,9966‿124904,10033‿9900000,46415‿144224,99500‿¯99000,100500‿1006766,11246‿99997,88753‿2,10517‿1908553,95135‿600000,¯100000‿47712,9531‿138629,¯332193‿158496,¯4988‿179175,9983‿14112,10016‿1001787,10033‿¯14255,9966‿99505⟩ + +# •rand / •MakeRand +0 (•MakeRand 0).Range¨↕2 %% ⟨⟩‿⟨⟩ +0‿0 (•MakeRand 0).Range¨↕2 %% ⟨⟩‿⟨⟩ +(•MakeRand 0).Deal 0 %% ⟨⟩ +0 (•MakeRand 0).Subset 0 %% ⟨⟩ +{!(∧•rand.Deal 𝕩)≡↕𝕩}¨ ⥊ ¯1‿0‿1+⌜2⋆↕22 # %SLOW +!"(rand).Range: Result rank too large (256≡≢𝕨)" % (256⥊1) •rand.Range 0 +! ≡˝ a←{r←•MakeRand 𝕩 ⋄ ⟨r.Range 1e9, 100 r.Range 1e9, r.Deal 100, 100 r.Deal 200, 100 r.Deal 200⟩}¨ 2‿2⥊↕2 ⋄ !∘≢¨´ ⊏a + +# •bit +!"•bit._cast: 𝕩 must have rank at least 1" % 8‿1 •bit._cast 123 +(↕10) {! (𝕨⥊¯1) ≡ 1‿𝕩•bit._cast (𝕨×𝕩)⥊1}⌜ 8‿16‿32 +%USE var ⋄ {t←𝕩⊏1‿8‿16‿32‿64 ⋄ !∘≡¨⟜⊏ r←{t•bit._cast 𝕩 V a}¨ LV a← ↕128 ⋄ ⊑⊑r}¨ ↕4‿4 +%USE var ⋄ {t←𝕩⊏1‿8‿16‿32‿64 ⋄ !∘≡¨⟜⊏ r←{t•bit._cast 𝕩 V a}¨ LV a←4=↕128 ⋄ ⊑⊑r}¨ ↕4‿4 +! 10‿1 ≡ ≢8‿16•bit._cast c←0↓2↕'a'+11 •rand.Range 26 ⋄ ! 10‿2 ≡ ≢c +! 10‿1 ≡ ≢8‿16•bit._cast c← 2↕'a'+11 •rand.Range 26 ⋄ ! 10‿2 ≡ ≢c + + + + + +# CBQN-specific extensions + +# •_while_ +1⊸+•_while_{𝕊: ∧´𝕩≤20} ↕10 %% 12+↕10 +(10⥊1) +•_while_{𝕊: ∧´𝕩≤20} ↕10 %% 12+↕10 + +# •Hash +! ≡´ •Hash¨ 2⥊<⟨10,"ab"⟩ +! ≡´1 •Hash¨ 2⥊<⟨10,"ab"⟩ + +# •ToUTF8 +@-˜•ToUTF8 "𝕩⍉hello" %% 240‿157‿149‿169‿226‿141‿137‿104‿101‿108‿108‿111 + +# •FromUTF8 +! •FromUTF8∘•ToUTF8⊸≡ "𝕩⍉hello" + +# •internal.GC +•internal.GC ↕10 %% 1 +# •internal.Type & •internal.Variation & •internal.ElType & •internal.ListVariations +( + raw ← {("a"⊸⋈¨ 𝕩)∾"s"⊸⋈¨ 1↓𝕩} ⟨"b","i8","i16","i32","f64","c8","c16","c32","h","f"⟩ + var ← {a‿e: ∾⟨a-32, e⟩}¨ raw + ty ← {∾⌽ {"a":"arr";"slice"}‿{"b":"bit"; "f":"fill"; 𝕩} {𝕎𝕩}¨ 𝕩}¨ raw + ty {"type"‿𝕨‿𝕩 ! 𝕨 ≡ •internal.Type 𝕩 •internal.Variation ⟨⟩}¨ var + ! 0‿1‿2‿3‿4‿5‿6‿7‿8‿8‿1‿2‿3‿4‿5‿6‿7‿8‿8 ≡ {•internal.ElType 𝕩 •internal.Variation ⟨⟩}¨ var + # TODO test •internal.ListVariations +) + +# •internal.Keep +•internal.Keep ↕10 %% ↕10 +!"This function can't be called dyadically" % 1 •internal.Keep 1 +# •internal.Refc +•internal.Refc •internal.Unshare ↕10 %% 1 +a←•internal.Unshare ↕10 ⋄ b←10⥊1) 2•rand.Range n}¨1+↕500 +{! 0≡2⊑•internal.Temp (2⋆63)⌾(𝕩⊸⊑) 10⥊0}¨ ↕10 +⟨2⋆63, 1.5, 0÷0⟩ {! 0≡2⊑•internal.Temp 𝕨⌾(𝕩⊸⊑) 20⥊0}⌜ ↕20 +≠{! 0‿0‿1 ≡ •internal.Temp 𝕩↑(𝕩⥊0)∾10⥊0÷0}¨ 1+↕10 diff --git a/test/cases/under.bqn b/test/cases/under.bqn new file mode 100644 index 00000000..b171bc1f --- /dev/null +++ b/test/cases/under.bqn @@ -0,0 +1,93 @@ +# ¨ & ˘ +# !% ⊢⌾(⊢¨) 4 # TODO enable +# !% ⊢⌾(⊢˘) 4 # TODO enable + +# ⊏ & ⊑ +!"𝔽⌾(a⊸⊑): Incompatible result elements" % 10‿20⌾(⟨1‿2,1‿2⟩⊸⊑) 4‿5⥊↕9 +!"𝔽⌾(a⊸⊏): Incompatible result elements" % 10‿20⌾(3‿3⊸⊏) ↕10 +!"𝔽⌾(a⊸⊏)𝕩: 𝔽 must return an array with the same shape as its input (expected ⟨2⟩, got ⟨3⟩)" % 10‿20‿30⌾(2‿3⊸⊏) ↕10 +!"𝔽⌾(a⊸⊏)𝕩: 𝔽 must return an array with the same shape as its input (expected ⟨2⟩, got ⟨3⟩)" % 1⊸∾⌾(2‿3⊸⊏) ↕10 +!"𝔽⌾(a⊸⊑)𝕩: 𝔽 must return an array with the same shape as its input (expected ⟨2⟩, got ⟨3⟩)" % 10‿20‿30⌾(⟨1‿2,2‿1⟩⊸⊑) 4‿4⥊↕16 +!"𝔽⌾(a⊸⊑)𝕩: 𝔽 must return an array with the same shape as its input (expected ⟨2⟩, got ⟨3⟩)" % 1⊸∾⌾(⟨1‿2,2‿1⟩⊸⊑) 4‿4⥊↕16 + + +# ⊑ +!"𝔽⌾(n⊸⊑)𝕩: reading out-of-bounds (n≡¯10, 3≡≠𝕩)" % 1⊸+⌾(¯10⊸⊑) ↕3 +!"⊑: 𝕨 contained list with mixed-type elements" % 'a'⌾(1‿'a'⊸⊑) 4‿5⥊↕9 +!"⊑: Indexing out-of-bounds (index 1‿5 in array of shape 4‿5)" % 'a'⌾(1‿5⊸⊑) 4‿5⥊↕9 +⟨10,20‿30⟩⌾(⟨1‿2,⟨1‿3,2‿1⟩⟩⊸⊑) 4‿5⥊↕9 %% 4‿5⥊0‿1‿2‿3‿4‿5‿6‿10‿20‿0‿1‿30‿3‿4‿5‿6‿7‿8‿0‿1 +!"⊑: Picking item at wrong rank (index 1‿1‿1 in array of shape 10‿10)" % 1¨⌾(1‿1‿1⊸⊑) 10‿10⥊1 +!"⊑: Picking item at wrong rank (index ⟨1⟩ in array of shape 10‿10)" % 1¨⌾(⟨1⟩⊸⊑) 10‿10⥊1 +a←10‿10‿10⥊↕1000 ⋄ ! a ≡ a⌾((↕≢a)⊸⊑) a +≠{𝕊: a←(1+•rand.Range 200)•rand.Range 2 ⋄ i←•rand.Range≠a ⋄ ! a ≡ (i⊑a)⌾(i⊸⊑) 2⌾(i⊸⊑) a}¨↕10000 +100⊸+⌾(5⊸⊑) ⥊↕4‿4 %% (100×5=↕16) + ⥊↕4‿4 +100⊸+⌾(¯5⊸⊑) ⥊↕4‿4 %% (100×11=↕16) + ⥊↕4‿4 +100⊸+⌾⊑ ⥊↕4‿4 %% (100×16↑1) + ⥊↕4‿4 +1⊸+⌾(¯2⊸⊑) ⥊↕4 %% 0‿1‿3‿3 +1⊸+⌾(¯2⊸⊑) ⥊0.5+↕4 %% 0.5‿1.5‿3.5‿3.5 +# !% ⊢⌾⊑ 4 # TODO enable +# !% ⊢⌾(⊑⊑) 4 # TODO enable + +# ⊏ +n←500 ⋄ a←↕n ⋄ i←(-n)+↕2×n ⋄ r←⌽(2×n)⥊a ⋄ ! (⌽a) ≡ r⌾(i⊸⊏) a +!"𝔽⌾(a⊸⊏)𝕩: Indexing out-of-bounds (¯11∊a, ⟨10⟩≡≢𝕩)" % 1‿2⌾(5‿¯11⊸⊏) ↕10 +!"𝔽⌾(a⊸⊏)𝕩: Indexing out-of-bounds (10∊a, ⟨10⟩≡≢𝕩)" % 1‿2⌾(9‿10⊸⊏) ↕10 +100⊸+⌾(⟨1‿2‿4⟩⊸⊏) <¨↕10 %% <¨ 0‿101‿102‿3‿104‿5‿6‿7‿8‿9 +100⊸+⌾(1‿2‿4⊸⊏) <¨↕10 %% <¨ 0‿101‿102‿3‿104‿5‿6‿7‿8‿9 +100⊸+⌾(1‿2‿4⊸⊏) ↕10 %% 0‿101‿102‿3‿104‿5‿6‿7‿8‿9 +100⊸+¨⌾(1‿2‿4⊸⊏) ↕10 %% 0‿101‿102‿3‿104‿5‿6‿7‿8‿9 +100⊸+⌾(1‿2‿¯4⊸⊏) <¨↕10 %% <¨ 0‿101‿102‿3‿4‿5‿106‿7‿8‿9 +100⊸+⌾(1‿2‿¯4⊸⊏) ↕10 %% 0‿101‿102‿3‿4‿5‿106‿7‿8‿9 +!"𝔽⌾(a⊸⊏): Incompatible result elements" % 3‿4⌾(1‿1⊸⊏) ↕10 +!"𝔽⌾(a⊸⊏): Incompatible result elements" % 3‿4⌾(1‿¯9⊸⊏) ↕10 +!"𝔽⌾(a⊸⊏): Incompatible result elements" % 3‿4‿5⌾(1‿1‿2⊸⊏) ↕10 +!"𝔽⌾(a⊸⊏): Incompatible result elements" % 3‿4‿5⌾(1‿1‿2⊸⊏) <¨↕10 +!"𝔽⌾(a⊸⊏): Incompatible result elements" % 3‿4‿5⌾(1‿1‿2⊸⊏) a←<¨↕10 ⋄ •internal.Keep a +!"𝔽⌾(a⊸⊏): Incompatible result elements" % 3‿4⌾(("Ah"•internal.Variation 1‿1)⊸⊏) <¨↕10 +20‿20⌾(1‿1⊸⊏) ↕10 %% 0‿20∾2+↕8 +100⊸+⌾(1‿2‿¯1⊸⊏) ↕5 %% 0‿101‿102‿3‿104 +100⊸+⌾(1‿2‿¯1⊸⊏) <¨↕5 %% <¨ 0‿101‿102‿3‿104 +1⊸+⌾(((100⥊↕10)∾10/↕10)⊸⊏) ↕10 %% 1+↕10 + + +# ⥊ +!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (16 ≡ ≢⥊𝕩, ⟨17⟩ ≡ shape of result of 𝔽)" % 1⊸∾⌾⥊ 4‿4⥊↕16 +1⊸+⌾⥊ 5 %% (<6) +1⊸+⌾⥊ <5 %% (<6) +1⊸+⌾⥊ ⥊5 %% (⥊6) +1⊸+⌾⥊ ↕2 %% 1‿2 +1⊸+⌾⥊ 2‿3⥊↕6 %% (1+2‿3⥊↕6) +⌽⌾⥊ 2‿3⥊↕6 %% (2‿3⥊⌽↕6) +!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (1 ≡ ≢⥊𝕩, ⟨2⟩ ≡ shape of result of 𝔽)" % 1⊸∾⌾⥊ 4 +!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (1 ≡ ≢⥊𝕩, ⟨2⟩ ≡ shape of result of 𝔽)" % 1⊸∾⌾⥊ <4 +!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (1 ≡ ≢⥊𝕩, ⟨2⟩ ≡ shape of result of 𝔽)" % 1⊸∾⌾⥊ ⥊4 +!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (2 ≡ ≢⥊𝕩, ⟨3⟩ ≡ shape of result of 𝔽)" % 1⊸∾⌾⥊ 1‿2 +!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (6 ≡ ≢⥊𝕩, ⟨7⟩ ≡ shape of result of 𝔽)" % 1⊸∾⌾⥊ 2‿3⥊↕6 +!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (1 ≡ ≢⥊𝕩, ⟨⟩ ≡ shape of result of 𝔽)" % ⊑⌾⥊ 4 +!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (1 ≡ ≢⥊𝕩, ⟨⟩ ≡ shape of result of 𝔽)" % ⊑⌾⥊ <4 +!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (1 ≡ ≢⥊𝕩, ⟨⟩ ≡ shape of result of 𝔽)" % ⊑⌾⥊ ⥊4 +!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (2 ≡ ≢⥊𝕩, 2‿1 ≡ shape of result of 𝔽)" % 2‿1⊸⥊⌾⥊ 1‿2 +# !% ⊢⌾⥊ 4 # TODO enable +# !% ⊢⌾(3⥊⊢) 4 # TODO enable + + +# / +!"/: Lengths of components of 𝕨 must match 𝕩 (3 ≠ 10)" % 1⊸∾⌾(1‿0‿1⊸/) ↕10 +10⊸+⌾(⟨1,0‿1⟩⊸/)↕2‿2 %% 2‿2⥊⟨0‿0,10‿11,1‿0,11‿11⟩ +!"𝔽⌾(a⊸/): Incompatible result elements" % 1‿2⌾(2‿0⊸/)↕2 +1⊸+⌾((↕10)⊸/) ↕10 %% ×⊸+ ↕10 + +# ↓ & ↑ +!"𝔽⌾(n⊸↑)𝕩: 𝔽 must return an array with the same shape as its input (2 ≡ n, ⟨1⟩ ≡ shape of result of 𝔽)" % ⟨1⟩⌾(2⊸↑) ↕4 +!"𝔽⌾(n⊸↓)𝕩: 𝔽 must return an array with the same shape as its input (2 ≡ n, ⟨1⟩ ≡ shape of result of 𝔽)" % ⟨1⟩⌾(2⊸↓) ↕4 +!"𝔽⌾(n⊸↑)𝕩: 𝔽 must return an array with the same shape as its input (¯2 ≡ n, ⟨3⟩ ≡ shape of result of 𝔽)" % 1⊸∾⌾(¯2⊸↑) ↕4 +!"𝔽⌾(n⊸↓)𝕩: 𝔽 must return an array with the same shape as its input (¯2 ≡ n, ⟨3⟩ ≡ shape of result of 𝔽)" % 1⊸∾⌾(¯2⊸↓) ↕4 +!"𝔽⌾(n⊸↓)𝕩: 𝔽 must return an array with the same shape as its input (5 ≡ n, ⟨1⟩ ≡ shape of result of 𝔽)" % ⟨1⟩⌾(5⊸↓) ↕4 +!"𝔽⌾(n⊸↓)𝕩: 𝔽 must return an array with the same shape as its input (1 ≡ n, 4‿5‿2 ≡ shape of result of 𝔽)" % ⍉⌾(1⊸↓) 3‿4‿5⥊↕60 +!"𝔽⌾(n⊸↑)𝕩: 𝔽 must return an array with the same shape as its input (¯2 ≡ n, 4‿5‿2 ≡ shape of result of 𝔽)" % ⍉⌾(¯2⊸↑) 3‿4‿5⥊↕60 +!"𝔽⌾(n⊸↑)𝕩: Cannot modify fill with Under (5 ≡ n, ⟨4⟩ ≡ ≢𝕩)" % ⊢⌾(5⊸↑) ↕4 +⟨⟩⌾(4⊸↓) ↕4 %% ↕4 +⟨⟩⌾(5⊸↓) ↕4 %% ↕4 +•internal.Keep⌾(¯5⊸↓) ↕4 %% ↕4 +{!(a×1+9× 0‿1‿2∊𝕩+↕3) ≡ 10⊸×⌾(𝕩⊸↓) a←3‿4‿5⥊↕60}¨ ¯5+↕10 +{!(a×1+9׬0‿1‿2∊𝕩+↕3) ≡ 10⊸×⌾(𝕩⊸↑) a←3‿4‿5⥊↕60}¨ ¯3+↕7 diff --git a/test/run.bqn b/test/run.bqn new file mode 100644 index 00000000..930be935 --- /dev/null +++ b/test/run.bqn @@ -0,0 +1,200 @@ +NextIdx ← {i←/𝕩 ⋄ (i∾≠𝕩)⊏˜i⍋𝕨} # for each index 𝕨, find the index of the next 1 in mask 𝕩 +UM ← {(≠𝕨)↑/⁼𝕩} +Fail ← {•Out 𝕩 ⋄ •Exit 1} +Trim ← {((∨`⌾⌽∧∨`)𝕩≠' ')/𝕩} + +{ 𝕊: + •Out "Usage: test/run.bqn [options | files]" + •Out "Options:" + •Out " lint Check that every test either is expected to return a specific value, error, or contains a '!'" + •Out " slow Enable slow tests" + •Out " noerr Disable erroring tests (ones expected to, or which contain ⎊)" + •Out " heapverify Disable tests that aren't runnable in heapverify" + •Out " debug Disable tests that aren't runnable in debug" + •Out " update-messages Auto-update error messages in tests" + •Out " ignore-messages Don't warn about incorrect error messages" + •Out " bin-search Binary search for some property. Next argument should be /[01]*/, with a 1 appended every time the property is matched, and a 0 otherwise" + •Out "Files:" + •Out " General:" + •Out " prims cells syntax system fills hash patterns under" + •Out " More special:" + •Out " fuzz perf" + •Out " For specific configurations:" + •Out " test_range // -DTEST_RANGE" + •Out "Lint all: test/run.bqn lint prims cells syntax system fills hash patterns under fuzz perf test_range" + •Exit 0 +}⍟⊢ (0=≠•args) ∨´ "help"‿"h"‿"?"∊'-'⊸≠⊸/¨•args + +o ← { + args ← •args + search ⇐ @ + { + n←»𝕩 + search ↩ '0'-˜⊑(n/args)∾<"" + ! ∧´search∊0‿1 + search ↩ search∾1 + args ↩ (¬n∨𝕩)/args + }⍟(∨´) "bin-search"⊸≡¨ args + named ← "run"‿"lint"‿"update-messages"‿"slow"‿"ignore-messages"‿"noerr"‿"heapverify"‿"debug" + i ← named⊐args + run ⇐ ∨´i=0 + lint ⇐ ∨´i=1 + update ⇐ ∨´i=2 + slow ⇐ ∨´i=3 + errm ⇐¬∨´i=4 + noerr ⇐ ∨´i=5 + heapverify ⇐ ∨´i=6 + debug ⇐ ∨´i=7 + noerr∨↩ heapverify + files ⇐ (i=≠named)/args + run ↩ update ∨ ¬∨´lint‿update +} + +searchRefine ← { + searchI ← 0 + { + o.search≡@? 𝕩; + searchI≡≠o.search? 𝕩; + 1≡≠𝕩? 𝕩; + SearchRefine (⌊2÷˜≠𝕩) ((searchI+↩1) ⊢ searchI⊑o.search)◶↓‿↑ 𝕩 + } +} + +exitCode ← 0 +Run ← { 𝕊 testname: + lns ← •FLines fullfile ← "cases"•file.At filename ← testname∾".bqn" + defk‿defv ← ⟨⟩‿⟨⟩ + i ← 0 + Pos ← {∾⟨filename, ":", •Repr 1+𝕩⟩} + Next ← {𝕊: (i+↩1) ⊢ i⊑lns} + Process ← { + "%DEF "≡5↑𝕩? + defk‿defv∾¨↩<¨ {(Process 1↓𝕩).str}⌾(1⊸⊑) ⊑∘⊐⟜' '⊸(↑⋈↓) 5↓𝕩 + @ + ; + "":@ + ; + '#'≡⊑𝕩? @ + ; + "("≡𝕩? + Process ∾ ∾⟜(@+10)¨ ¯1↓ ∾⟜<⟜Next•_while_{")"≢¯1⊑𝕩} ⟨Next@⟩ + ; + # insert defs + si ← /(≠𝕩)↑"%USE"⍷𝕩 + mi ← si+5 + ei ← mi NextIdx ¬𝕩∊'_'∾∾"0aA"+⟜↕¨10‿26‿26 + g ← (+`+´ 𝕩⊸UM¨ si‿mi‿ei) ⊔ 𝕩 + pre ← ⊑g + [·,uk,post] ← ⍉↑‿3⥊1↓g + {Fail (Pos i)∾": Unknown def "∾⊑𝕩⊏uk}⍟≠ /¬uk∊defk + str ← pre ∾ ∾((defk⊐uk)⊏defv) ∾¨ post + + Flag ← { + m ← (≠str)↑ 𝕩⍷str + str /˜↩ ¬ ∨⟜»⍟(¯1+≠𝕩) m + ∨´m + } + + {ln⇐i-1 ⋄ fast⇐¬Flag"%SLOW" ⋄ debug⇐¬Flag"%NDEBUG" ⋄ heapverify⇐¬Flag"%NHEAPVERIFY" ⋄ str⇐str} + } + tests ← SearchRefine @⊸≢¨⊸/ ∾⟜<⟜(Process∘Next)•_while_{𝕊: i≠≠lns} ⟨⟩ + {𝕊: •Out "Narrowed down to test "∾Pos (⊑tests).ln}⍟⊢ (o.search≢@)∧1=≠tests + + + tests { 𝕊ns: ⟨ln,str⟩←ns + idx ← ⊑str⊐'%' + { + idx ≡ ≠str? ⟨ns, "eval", str⟩; + (i2←idx+1)<≠str? '%'≡i2⊑str? ⟨ns, "equal", idx↑str, (2+idx)↓str⟩; + {𝕊: Fail (Pos ln)∾": Unknown test format"}⍟⊢ '!'≢⊑str + ⟨ns, "error", (idx+1)↓str, 1↓idx↑str⟩ + } + }¨↩ + + { 𝕊 d: + ln←(⊑d).ln + ty←1⊑d + Lint ← {𝕊: •Out ∾⟨"Lint: ", Pos ln, ": ", 𝕨⟩}⍟(¬⊢) + { + "eval"≡ty? "No check or assert" Lint ∨´'!'=2⊑d; + @ + } + }¨⍟o.lint tests + + { 𝕊: + badCount ← 0 + badMessage ← 0 + currLn ← 0 + skipped ← 0 + dir ← •file.At "testDir" + •file.CreateDir⍟(¬•file.Exists) dir + Bad ← { + ""𝕊𝕩; + •Out ∾⟨Pos currLn, ": ", 𝕩⟩ + •Out¨ " "⊸∾¨ 𝕨 + badCount+↩ 1 + } + ErrMsg ← {𝕊: m←•CurrentError@ ⋄ {1==m? ∧´2=•Type¨m? m; •Repr⎊"(unrepresentable)" m}} + Eval ← {⟨dir, ∾⟨testname,"_line_",•Repr currLn+1,".bqn"⟩, ⟨"arg0",1⟩⟩ •BQN 𝕩} + EvalS ← •BQN⎊{𝕊: Bad "Bad comparison value" ⋄ "(bad)"} + toRun ← tests + toRun {{𝕩.fast }∘⊑¨⊸/𝕩}⍟(¬o.slow)↩ + toRun {{𝕩.debug }∘⊑¨⊸/𝕩}⍟o.debug↩ + toRun {{𝕩.heapverify}∘⊑¨⊸/𝕩}⍟o.heapverify↩ + skipped+↩ (≠tests)-≠toRun + results ← { + "eval"‿str: { + o.noerr? ⊑'⎊'∊str? skipped+↩1; + Eval⎊{𝕊: Bad "Expected success, got error: "∾ErrMsg@} str + @ + }; + "error"‿str‿exp: { + o.noerr? skipped+↩1; + ok‿got ← (1⋈Eval)⎊(0⋈ErrMsg) str + exp ↩ EvalS⍟{×≠Trim𝕩} exp + { + (got≡exp) ∧ ¬ok? @; + ok? Bad "Expected error, but didn't get one" ⋄ @; + ⟨"Expected: "∾exp ⋄ "Got: "∾got⟩ Bad⍟o.errm "Wrong error message" + badMessage+↩ 1 + got + } + }; + "equal"‿str‿exp: { + o.noerr? ⊑'⎊'∊str? skipped+↩1; + ok‿got ← (1⋈Eval)⎊(0⋈ErrMsg) str + exp ↩ EvalS exp + { + ¬ok? Bad "Expected value, but got error: "∾got; + got •internal.EEqual exp? @; + ⟨"Expected: "∾•Repr exp ⋄ "Got: "∾•Repr got⟩ Bad "Wrong value" + @ + } + @ + } + }∘{currLn↩(⊑𝕩).ln ⋄ 1↓𝕩}¨ toRun + + {𝕊: + res‿desc ← ({@≡𝕩? 0; ¬⊑(@+10)∊𝕩}¨ results)⊸/¨ results‿toRun + 0≠≠res? + •Out ∾⟨"Update ", •Repr≠res, " entr", (1<≠res)⊑"y"‿"ies", " in ", filename, "?"⟩ + { + ¬⊑"yY"∊˜⊑'n'∾˜•GetLine@? •Out "Not updating."; + [idxs, upd] ← ⍉>res {new𝕊⟨⟨ln⟩, "error", str, ·⟩: ln ⋈ ∾⟨"!", •Repr new, " %", str⟩}¨ desc + "Refusing to write over changed file" ! lns ≡ •FLines fullfile + fullfile •FLines lns {×≠𝕩? ⋈⁼𝕩; 𝕨}¨ (≠lns)↑idxs⊔upd + •Out "Updated." + } + ;@ + }⍟⊢ o.update + skipm ← (×skipped)/∾⟨" (", •Repr skipped, " skipped)"⟩ + { + 0=badCount? •Out filename∾": "∾(•Repr≠toRun)∾" passed!"∾skipm; + •Out ∾⟨•Repr (≠toRun)-badCount, '/', •Repr≠toRun⟩ ∾ ((¬o.errm)∧×badMessage)/∾⟨"; ", •Repr badMessage, " mismatched error message", (1≠badMessage)/"s"⟩∾skipm + exitCode ↩ 1 + } + }⍟o.run @ +} +Run¨ SearchRefine o.files + +•Exit⍟(0⊸≠)⍟(¬o.heapverify) exitCode \ No newline at end of file