aboutsummaryrefslogtreecommitdiff
path: root/src/f.bqn
blob: c00b43a5377b9449b53a440727bb06f7c0d9a7b0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# Format an array to a string including newlines
{
  ⟨Type,Decomp,FF,FNβŸ©β†π•©
  ReprAtom ← <⟜@β—ΆβŸ¨@βŠΈβ‰ β—ΆβŸ¨"@","'"⊸(∾∾⊣)⟩,FN⟩

  # Vertical padding for arrays of rank greater than 2
  PadCount ← {
    # Empty lines after each row: 1 if it's at the end of a 2-cell, plus
    # 1 if it's at the end of a 2-cell and a 3-cell, and so on
    # But none at the very end
    0⌾(Β―1βŠΈβŠ‘) β₯Š 𝕨 +βŽ‰Β―1β€ΏβˆžΒ΄ Γ—βŒœΛœ`⌾⌽ (-𝕩)↑¨1
  }
  PadV ← {
    # Leading shape and padding count
    p ← PadCount 1 ⌈ ls ← Β―1↓≒𝕩
    # If 𝕩 has cells, pad by selection; if it's empty, there are only
    # pads but selection would try to get cells (1⌈ above), so overtake.
    Pad ← {(»⊸<βŠΈΓ—/0∾1+𝕨) ⊏ ' 'Β¨βˆ˜βŠβŠΈβˆΎπ•©}
    p (0<β‰ βˆ˜βŠ’)β—ΆβŸ¨+Β΄βŠΈβ†‘,Pad⟩ ((Γ—Β΄ls)∾¯1↑≒𝕩) β₯Š 𝕩
  }⍟(2 < =)
  PadVMixed ← {
    # PadV, but with 2-cells enclosed: they might have different lengths
    ∾ (1 PadCount ≒𝕩) (βŠ’βˆΎβ‰βŸœ(Β―1βŠ‘β‰’)β₯Š' 'Λ™)Β¨ β₯Šπ•©
  }

  # Horizontal padding: just some spaces on either side
  PadH ← { sβ†βŸ¨β‰ π•©,π•¨βŸ©β₯Š' ' β‹„ βˆΎβ‰βŸ¨s,𝕩,s⟩ }

  # Add a frame to padded data
  Enframe ← βˆ¨β—‹(1βŠΈβ‰ )βŸœβ‰ β—Ά{∨´2=+`-˝"⟨⟩"=βŒœβŠπ•©}β€Ώ1β—Ά{
    # One-line version
    ≍"⟨"∾(Β―1↓1β†“βŠπ•©)∾"⟩"
  }β€Ώ{
    # General case
    l ← Β―1 βŠ‘ ≒𝕩
    ∾ ⟨
      ≍lβ†‘βˆΎβŸ¨"β”Œ",(5⊸<)β—ΆβŸ¨β₯Š"·─"⊏˜1⌊⊒,FNβŸ©π•¨βŸ©
      ((0⌈4βŒŠπ•¨-1)βŠ‘"Β·β•΅β•Žβ”†β”Š")βŒΎβŠ‘ 𝕩
      ≍l-βŠΈβ†‘"β”˜"
    ⟩
  }

  FmtEmpty ← (0β€Ώ0β‰’β‰’)β—Ά("β”Œβ”"≍"β””β”˜")β€Ώ(((2β‰ =)∨0=β‰ )β—Ά{
    '┐'⌾(0β€ΏΒ―1βŠΈβŠ‘) 2 Enframe 1 PadH ' '¨𝕩
  }β€Ώ{
    ≍(1<β‰ )β—ΆβŸ¨"⟨⟩",'↕'βŒΎβŠ‘Β·βˆΎΒ·"β€Ώ"⊸∾¨FNΒ¨βŸ©β‰’π•©
  })

  _paddingJoin ← {  # 𝕗 is 1 to left align and Β―1 to right align
    s ← β‰’Β¨ 𝕩
    w ← (0<=)β—ΆβŸ¨β₯Š,⌈˝⍟(=-1Λ™)⟩1βŠ‘Β¨s
    h ← βŒˆΛβŽ‰1⍟(0<=) βŠ‘Β¨s
    o ← <βˆ˜βˆΎβŽ‰2 β‰βŸ(0⌈2-=) (h β‹ˆβŒœ 𝕗×wΒ¬(-𝕗×≠w)↑1) ↑¨ 𝕩
    2 PadH (1βŠΈβŒ½βŠΈβ‰‘β₯Šh)β—ΆβŸ¨PadVMixed,PadV∘>⟩ o
  }

  _fmtMixedP ← {
    r ← =𝕩
    Join ← r Enframe 𝕗 _paddingJoin
    𝕨 (∨´<⟜∞)β—Ά(Join <⊸(FmtΒ¨))β€Ώ{
      p ← ⟨r>1,2⟩  # Outer padding
      o ← Β―1((0+⌜´(1(1+Γ—)`⊒)βŒΎβŒ½Γ—β†•Β¨)βˆ˜β†“β‹ˆβŒœ2Γ—β†•βˆ˜βŠ‘)≒𝕩  # Offset
      E ← (1β€Ώ1β₯Š'…')Λ™
      f ← o (𝕨-p)⊸-⊸(⊣ E∘⊒⍟(∨´<βŸœβ‰’) (βˆ¨Β΄β‰€βŸœ0)β—ΆFmtβ€ΏE)Β¨ 𝕩
      Join f
    } 𝕩
  }
  FmtMixed ← 1 _fmtMixedP

  FmtSimple ← (β‰ (0⊸<+≀)+Β΄)∘(β₯Š<@Λ™)βˆ˜βŠ’β—Ά{ # Depth 1
    # All characters
    r ← =𝕩 β‹„ 𝕩 ↩ ><Β¨0↓𝕩  # Ensure rank>0 and ' ' for fill
    k ← ∞⍟(0⊸=) -β‰  c ← Β―1↓≒𝕩
    q ← "'"""βŠ‘Λœ0<r
    # Escape quotes in strings (rank 1) and substitute control chars
    # with control pictures for other ranks.
    CSub ← { 𝕩 + (𝕩(=Γ—'␑'-⊒)@+127) + ('␀'-@)×𝕩<@+32 }
    𝕩 ↩ (1β‰ r)β—ΆβŸ¨(1+q=⊒)⊸/,Csub⟩ 𝕩
    (r Enframe 1 PadH PadV)⍟(1β‰ r) ≍ (qβŒΎβŠ‘cβ₯Š(Β―1βŠ‘1∾c)↑'Β·') βˆΎβŽ‰k 𝕩 βˆΎβŽ‰k c-βŠΈβ†‘q
  }β€Ώ{
    # Not homogeneous, or empty
    (∨´0=β‰’)β—ΆβŸ¨π•¨βŠΈFmtMixed,FmtEmpty⟩ 𝕩
  }β€Ώ{
    # All numbers
    𝕨 Β―1 _fmtMixedP 𝕩
  }

  # Format data type
  FmtDat ← (2βŒŠβ‰‘βˆ˜βŠ’)β—ΆβŸ¨
    ≍ ReprAtom∘⊒
    (∨´∘β₯Š3≀Type⌜∘⊒)β—ΆFmtSimpleβ€ΏFmtMixed
    FmtMixed
  ⟩

  # Format part of a compound operation; return precedenceβ€Ώstring
  _dispOp_ ← {
    FmtComp ← Type (3β‰€βŠ£)β—ΆβŸ¨0β‹ˆΒ·π”½βŠ’, π•ŠβŸ© ⊒
    k ← βŠ‘ d ← Decomp 𝕩
    p ← k βŠ‘ "00321111"-'0'
    Paren ← "("∾∾⟜")"
    FromComp ← ∾(⌽⍟(p>1)Β·-0=β†•βˆ˜β‰ )(+βŸœβŠ‘Paren∘⊒⍟((2⌊p)β‰€βŠ£)1βŠΈβŠ‘)⟜FmtComp¨⊒
    s ← (2⌊|k)β—ΆβŸ¨β₯Šβˆ˜FF𝕩˙,π•¨π”ΎβŠ’,FromComp⟩ 1↓d
    s ↩ ∾⟜"{𝔽}"⍟(3>Β·Type Β―1βŠ‘dΛ™)⍟(2≀p) s
    pβ€Ώs
  }
  arr ← "*array*"
  FmtOp ← ≍1βŠ‘ (1=β‰ )β—ΆβŸ¨arr,⊏⟩∘FmtDat _dispOp_ (=⟜2β—ΆβŸ¨FFβŠ‘βˆ˜βŠ’,arr⟩)

  # Format any value to character matrix
  Fmt ← {
    t ← Type𝕩
    𝕨 (3≀t)β—ΆβŸ¨FmtDat,t⊸FmtOp⟩ 𝕩
  }
  Trunc ← {
    c ← 𝕨<s←≒ f ← 𝕩
    𝕨 {l←c-Λœπ•¨βŒŠs β‹„ lsβ†β‹ˆβŒœΒ΄l∾⟜(β₯ŠβŸœ1)Β¨c β‹„ ∾ ls β₯ŠΒ¨ (l↑f)βŒΎβŠ‘ '…'Β¨ ls}⍟(∨´c) f
  }
  FmtW ← {
    m ← "β€’Fmt: 𝕨 must be a list of up to two numbers (width, height)"
    m ! (1β‰₯=)β—ΆβŸ¨0,2β‰₯β‰ βŸ© 𝕨
    (βŒ½π•¨βŠ’βŠ˜Β»βˆžβ€Ώβˆž) (⊣ Trunc Fmt) 𝕩
  }

  # Represent as string
  RR ← {Repr𝕩}
  ReprList ← (0<β‰ )β—ΆβŸ¨"⟨⟩",(⌈´(2β€Ώ1β€Ώ0Β»7β₯Š2)⊏˜Type⌜)β—ΆβŸ¨
    '"' (⊣∾((1+=)/⊒)∾⊣) ⊒
    (1<β‰ )β—ΆβŸ¨"⟨"∾"⟩"«∾,1β†“βˆΎβŸ©("β€Ώ"∾ReprAtom)Β¨
    "⟨"∾"⟩"«·∾(","∾RR)¨
  ⟩⟩
  ReprArr ← (2⌊=)β—ΆβŸ¨"<"∾RRβˆ˜βŠ‘,ReprList,β‰’βˆΎβŸœ"β₯Š"βŠΈβˆΎβ—‹ReprListβ₯ŠβŸ©
  ReprDat ← (0=Type)β—ΆβŸ¨ReprAtom,ReprArr⟩
  ReprOp ← 1βŠ‘ RR _dispOp_ ("Can't represent block"!0Λ™)
  Repr ← Type (3β‰€βŠ£)β—ΆβŸ¨ReprDat⊒,ReprOp⟩ ⊒

  # Convert Fmt from matrix to string
  ⟨¯1↓·β₯Š ∾⟜(@+10)˘∘FmtW, Repr⟩
}