aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarshall Lochbaum <mwlochbaum@gmail.com>2020-10-31 22:31:14 -0400
committerMarshall Lochbaum <mwlochbaum@gmail.com>2020-10-31 22:31:14 -0400
commit4a0c297b28beb9b94c4f13b90672c02379a65e6b (patch)
treee7656c4c56e10835e0df5833863d802f09bc2a23 /src
parentfa5da41ea5a0762b7aeee8ad97522e215651d054 (diff)
Allow compiling explainer standalone with cjs.bqn e
Diffstat (limited to 'src')
-rwxr-xr-xsrc/cjs.bqn3
-rw-r--r--src/e.bqn3
-rw-r--r--src/ea.bqn109
3 files changed, 114 insertions, 1 deletions
diff --git a/src/cjs.bqn b/src/cjs.bqn
index abb16c47..f6ebf1d0 100755
--- a/src/cjs.bqn
+++ b/src/cjs.bqn
@@ -13,9 +13,10 @@ J ← ∾∾⟜(@+10)¨
Fout ← (≠↑⟨⊢,Fconst,L,⊢⟩˙) {L𝕎¨𝕩}¨ ⊢
Frun ← ("provide.concat("∾∾⟜")")⌾(1⊸⊑) Fout
Long ← ∾ (≠↑1‿3/⟨" new Uint8Array("∾∾⟜")"⋄((@+10)∾" ,")⊸∾⟩˙) {𝕎𝕩}¨ ⊢
-• ← (⊑"r"‿"c"‿"fmt"⊐⊏)◶⟨
+• ← (⊑"r"‿"c"‿"fmt"‿"e"⊐⊏)◶⟨
{𝕩⋄ref‿len←•Import"pr.bqn"⋄Long Frun len⊸↓⌾(1⊸⊑)Comp ref}
{𝕩⋄Long Fout Comp J •LNS "c.bqn"}
{𝕩⋄Long Fout Comp J •LNS "fmt.bqn"}
+ {𝕩⋄Long Fout Comp J ∾ •LNS∘∾⟜".bqn"¨ "ea"‿"../svg"‿"e"}
¯1 ↓ · J L∘Fout∘Comp¨
⟩ args
diff --git a/src/e.bqn b/src/e.bqn
index 5e8b4864..9511c4ad 100644
--- a/src/e.bqn
+++ b/src/e.bqn
@@ -1,3 +1,6 @@
+# Expression explainer: generates an svg diagram to show how a BQN
+# program is evaluated
+
wh ← 10.75‿24
pad← wh×2‿1
to ← 1+wh÷2‿3
diff --git a/src/ea.bqn b/src/ea.bqn
new file mode 100644
index 00000000..71953ba4
--- /dev/null
+++ b/src/ea.bqn
@@ -0,0 +1,109 @@
+# Syntax highlighting utilities for e.bqn; copied from ../md.bqn
+# It should be getting this information from the tokenizer instead
+
+Modify ← { ⟨include,add,pos⟩←𝕨
+ ((/include)∾(≠¨add)/pos) ⍋⊸⊏ (include/𝕩)∾∾add
+}
+
+# Return BQN highlights for an string 𝕩, as an ⟨add,pos⟩ list for Modify
+# (include will be all 1s).
+lf ← @+10
+FindGroup ← {
+ i ← (∾𝕨) ⊐ 𝕩 # Index in all cells of 𝕨
+ e ← +`≠¨𝕨 # Index past the end of each group of 𝕨
+ e ⍋ i # How many end-indices does each element pass?
+}
+Trace ← {
+ # 𝕨 is a list with one index for each possible start, giving a later
+ # start that is known to be enabled if that one is.
+ # 𝕩 is a mask of all starts known to be enabled.
+ # A "stop" position that follows all expressions tells when to stop.
+ # At each step the distance from a start to its successor in 𝕨 is
+ # doubled, so the maximum number of steps is about 2⋆⁼≠𝕩.
+ En ← {
+ 𝕩 ↩ 1¨⌾((𝕩/𝕨)⊸⊏)𝕩 # Starts following from an enabled one are enabled
+ 𝕨 ↩ ⊏˜ 𝕨 # Double the number of steps in 𝕨
+ 𝕨 En 𝕩 # Repeat
+ }⍟{0=¯1⊑𝕩} # until the stop is enabled
+
+ g ← ⍋𝕨 # Order expressions by starting index
+ start ← g⊏𝕨
+ end ← g⊏𝕩
+ next ← start ⍋ end # An expression's successor starts after it ends
+ next ∾↩ ≠next # The stop node is its own successor
+ enabled ← ¯1 ↓ next En (≠next)↑1 # Search and remove the stop
+ enabled / start≍˘end # List of enabled starts and ends
+}
+idChars ← ⟨
+ ('0'+↕10)∾"¯.π∞"
+ "𝕣"∾˜'a'+↕26
+ 'A'+↕26
+ "_"
+⟩
+GetHighlights ← {
+ # Characters used by BQN, and the HTML class they are associated with.
+ classes‿chars ← <˘ ⍉ ∘‿2⥊⟨
+ 0 , " "∾@+9‿10 # Should never be highlighted
+ "Value" , ¯1⊏˘5‿2⥊"𝕨𝕩𝕗𝕘𝕤"# Hack around UTF-16
+ "Function" , "+-×÷⋆√⌊⌈|¬∧∨<>≠=≤≥≡≢⊣⊢⥊∾≍↑↓↕«»⌽⍉/⍋⍒⊏⊑⊐⊒∊⍷⊔!"∾¯1⊏˘5‿2⥊"𝕎𝕏𝔽𝔾𝕊"
+ "Modifier" , "˙˜˘¨⌜⁼´˝`"
+ "Modifier2" , "∘○⊸⟜⌾⊘◶⎉⚇⍟⎊"
+ "Number" , ∾idChars # Will be classified among ↑↑ later
+ "Gets" , "←⇐↩→"
+ "Paren" , "()"
+ "Bracket" , "⟨⟩"
+ "Brace" , "{}"
+ "Ligature" , "‿"
+ "Nothing" , "·"
+ "Separator" , "⋄,"
+ "String" , "'""@"
+ "Comment" , "#"
+ ⟩
+ # Turn non-whitespace classes into ⟨open,close⟩ html tags.
+ classTag ← ""‿"" ∾ > {⟨"<span class='"∾𝕩∾"'>","</span>"⟩}¨ 1↓classes
+
+ # Find each character's group, sending unknowns to 1.
+ col ← (≠chars) (⊢--⟜1×=) chars FindGroup 𝕩
+
+ # Locate comments and strings.
+ c ← 𝕩='#'
+ le← /(𝕩=lf)∾1
+ # Line endings (le) end every comment (/c) on the line, so take a copy
+ # for each # before that line but not the previous.
+ ce← le /˜ -⟜» c/⊸⍋le
+ # A single quote can only be used if there's another two places down.
+ s ← /0‿0⊸«⊸∧𝕩='''
+ d ← /𝕩='"'
+ css ← ⟨ s ⋄ ¯1↓d ⋄ /c ⟩ # Comment or string start
+ cse ← ⟨ 2+s ⋄ 1↓d ⋄ ce ⟩ # Corresponding end indices
+ # Now b is a table of (start,end) pairs
+ b ← css Trace○∾ cse
+ # Given a list of pairs, get a mask indicating included regions
+ ToMask ← (≠`∨⊢) (≠𝕩)↑/⁼∘∾
+ # Split rows and group into text‿comments
+ tc ← ((⊏˘b)⊏c) 2{𝕗↑⊔○(∾⟜𝕗)} <˘b
+ # Color with "String" and "Comment"
+ col ⌈↩ +´ (2‿1-˜≠classes) × ToMask¨ tc
+
+ # UTF-16 hack: first half of a special name needs to match the second
+ col↩ («col) ⊣⌾((𝕩=⊑"𝕩")⊸/) col
+
+ # Color numeric literals and identifiers
+ id ← col=5 # ←→ 𝕩∊idChars
+ w ← »⊸< id # Word (identifier or number) beginning mask
+ wt ← idChars FindGroup w/𝕩 # Type based on first character
+ wt+↩ '_' = («⊸<id)/𝕩 # Modifier1 to Modifier2 based on word end
+ wt+↩ 5×0=wt # Shift 0 to Number
+ wi ← 1-˜+`id/w # Index of word containing each of /id
+ col↩(wi⊏wt)⌾(id⊸/) col
+
+ # Tags are placed at boundaries between different colors
+ boundary ← ¯1⊸»⊸≠ col
+ bcol ← boundary / col
+ # Windows gives us rows of start,end where the end position of one
+ # color is the start of the next
+ # Subtract one to place before the starting character
+ pos ← 2 ↕ 1-˜/boundary∾1
+ # Remove class 0 regions, as these don't use tags
+ (⥊ (0<bcol)⊸/)¨ ⟨bcol⊏classTag, pos⟩
+}