diff options
| -rw-r--r-- | docs/tutorial/expression.html | 150 | ||||
| -rw-r--r-- | md.bqn | 5 | ||||
| -rw-r--r-- | tutorial/evalexp.bqn | 46 | ||||
| -rw-r--r-- | tutorial/expression.md | 4 |
4 files changed, 129 insertions, 76 deletions
diff --git a/docs/tutorial/expression.html b/docs/tutorial/expression.html index cea81292..22da2272 100644 --- a/docs/tutorial/expression.html +++ b/docs/tutorial/expression.html @@ -119,37 +119,37 @@ <g font-family='BQN,monospace' font-size='18px'> <rect class='code' stroke-width='1' rx='10' x='-21.5' y='-24' width='204.25' height='168'/> <text><tspan class='Paren'>(</tspan><tspan class='Number'>4</tspan><tspan class='Function'>÷</tspan><tspan class='Number'>3</tspan><tspan class='Paren'>)</tspan> <tspan class='Function'>×</tspan> <tspan class='Number'>π</tspan> <tspan class='Function'>×</tspan> <tspan class='Number'>2</tspan><tspan class='Function'>⋆</tspan><tspan class='Number'>3</tspan></text> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M17.2 2.4v72h10.75'/> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M27.95 74.4v24h43'/> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M38.7 2.4v72h-10.75'/> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M70.95 98.4v24h-77.938'/> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M92.45 2.4v48h21.5'/> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M113.95 50.4v48h-43'/> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M135.45 2.4v24h10.75'/> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M146.2 26.4v24h-32.25'/> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M156.95 2.4v24h-10.75'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M156.95 2.4V26.4H146.2'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M135.45 2.4V26.4H146.2'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M146.2 26.4V50.4H113.95'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M92.45 2.4V50.4H113.95'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M113.95 50.4V98.4H70.95'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M38.7 2.4V74.4H27.95'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M17.2 2.4V74.4H27.95'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M27.95 74.4V98.4H70.95'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M70.95 98.4V122.4H-6.987'/> <g text-anchor='middle'> <g class='codeCover' stroke-width='6' stroke-linejoin='round'> - <text x='17.125' y='81'>4</text> - <text x='27.875' y='81'>÷</text> - <text x='38.625' y='81'>3</text> - <text x='70.875' y='105'>×</text> - <text x='92.375' y='57'>π</text> - <text x='113.875' y='57'>×</text> - <text x='135.375' y='33'>2</text> - <text x='146.125' y='33'>⋆</text> <text x='156.875' y='33'>3</text> + <text x='146.125' y='33'>⋆</text> + <text x='135.375' y='33'>2</text> + <text x='113.875' y='57'>×</text> + <text x='92.375' y='57'>π</text> + <text x='70.875' y='105'>×</text> + <text x='38.625' y='81'>3</text> + <text x='27.875' y='81'>÷</text> + <text x='17.125' y='81'>4</text> </g> <g font-size='15px' opacity='0.9'> - <text x='17.125' y='79'><tspan class='Number'>4</tspan></text> - <text x='27.875' y='79'><tspan class='Function'>÷</tspan></text> - <text x='38.625' y='79'><tspan class='Number'>3</tspan></text> - <text x='70.875' y='103'><tspan class='Function'>×</tspan></text> - <text x='92.375' y='55'><tspan class='Number'>π</tspan></text> - <text x='113.875' y='55'><tspan class='Function'>×</tspan></text> - <text x='135.375' y='31'><tspan class='Number'>2</tspan></text> - <text x='146.125' y='31'><tspan class='Function'>⋆</tspan></text> <text x='156.875' y='31'><tspan class='Number'>3</tspan></text> + <text x='146.125' y='31'><tspan class='Function'>⋆</tspan></text> + <text x='135.375' y='31'><tspan class='Number'>2</tspan></text> + <text x='113.875' y='55'><tspan class='Function'>×</tspan></text> + <text x='92.375' y='55'><tspan class='Number'>π</tspan></text> + <text x='70.875' y='103'><tspan class='Function'>×</tspan></text> + <text x='38.625' y='79'><tspan class='Number'>3</tspan></text> + <text x='27.875' y='79'><tspan class='Function'>÷</tspan></text> + <text x='17.125' y='79'><tspan class='Number'>4</tspan></text> </g> </g> </g> @@ -172,46 +172,46 @@ <g font-family='BQN,monospace' font-size='18px'> <rect class='code' stroke-width='1' rx='10' x='-21.5' y='-24' width='236.5' height='190'/> <text><tspan class='Paren'>(</tspan><tspan class='Function'>√</tspan><tspan class='Number'>3</tspan> <tspan class='Function'>+</tspan> <tspan class='Number'>2</tspan><tspan class='Function'>×√</tspan><tspan class='Number'>2</tspan><tspan class='Paren'>)</tspan> <tspan class='Function'>-</tspan> <tspan class='Number'>1</tspan><tspan class='Function'>+√</tspan><tspan class='Number'>2</tspan></text> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M17.2 115.9v19h118.25'/> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M27.95 1.9v95h21.5'/> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M49.45 96.9v19h-32.25'/> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M70.95 1.9v76h10.75'/> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M81.7 77.9v19h-32.25'/> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M92.45 58.9v19h-10.75'/> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M103.2 1.9v57h-10.75'/> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M135.45 134.9v19h-142.437'/> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M156.95 1.9v38h10.75'/> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M167.7 39.9v95h-32.25'/> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M178.45 20.9v19h-10.75'/> - <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M189.2 1.9v19h-10.75'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M189.2 1.9V20.9H178.45'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M178.45 20.9V39.9H167.7'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M156.95 1.9V39.9H167.7'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M167.7 39.9V134.9H135.45'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M103.2 1.9V58.9H92.45'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M92.45 58.9V77.9H81.7'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M70.95 1.9V77.9H81.7'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M81.7 77.9V96.9H49.45'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M27.95 1.9V96.9H49.45'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M49.45 96.9V115.9H17.2'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M17.2 115.9V134.9H135.45'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M135.45 134.9V153.9H-6.987'/> <g text-anchor='middle'> <g class='codeCover' stroke-width='6' stroke-linejoin='round'> - <text x='17.125' y='123'>√</text> - <text x='27.875' y='104'>3</text> - <text x='49.375' y='104'>+</text> - <text x='70.875' y='85'>2</text> - <text x='81.625' y='85'>×</text> - <text x='92.375' y='66'>√</text> - <text x='103.125' y='66'>2</text> - <text x='135.375' y='142'>-</text> - <text x='156.875' y='47'>1</text> - <text x='167.625' y='47'>+</text> - <text x='178.375' y='28'>√</text> <text x='189.125' y='28'>2</text> + <text x='178.375' y='28'>√</text> + <text x='167.625' y='47'>+</text> + <text x='156.875' y='47'>1</text> + <text x='135.375' y='142'>-</text> + <text x='103.125' y='66'>2</text> + <text x='92.375' y='66'>√</text> + <text x='81.625' y='85'>×</text> + <text x='70.875' y='85'>2</text> + <text x='49.375' y='104'>+</text> + <text x='27.875' y='104'>3</text> + <text x='17.125' y='123'>√</text> </g> <g font-size='15px' opacity='0.9'> - <text x='17.125' y='121'><tspan class='Function'>√</tspan></text> - <text x='27.875' y='102'><tspan class='Number'>3</tspan></text> - <text x='49.375' y='102'><tspan class='Function'>+</tspan></text> - <text x='70.875' y='83'><tspan class='Number'>2</tspan></text> - <text x='81.625' y='83'><tspan class='Function'>×</tspan></text> - <text x='92.375' y='64'><tspan class='Function'>√</tspan></text> - <text x='103.125' y='64'><tspan class='Number'>2</tspan></text> - <text x='135.375' y='140'><tspan class='Function'>-</tspan></text> - <text x='156.875' y='45'><tspan class='Number'>1</tspan></text> - <text x='167.625' y='45'><tspan class='Function'>+</tspan></text> - <text x='178.375' y='26'><tspan class='Function'>√</tspan></text> <text x='189.125' y='26'><tspan class='Number'>2</tspan></text> + <text x='178.375' y='26'><tspan class='Function'>√</tspan></text> + <text x='167.625' y='45'><tspan class='Function'>+</tspan></text> + <text x='156.875' y='45'><tspan class='Number'>1</tspan></text> + <text x='135.375' y='140'><tspan class='Function'>-</tspan></text> + <text x='103.125' y='64'><tspan class='Number'>2</tspan></text> + <text x='92.375' y='64'><tspan class='Function'>√</tspan></text> + <text x='81.625' y='83'><tspan class='Function'>×</tspan></text> + <text x='70.875' y='83'><tspan class='Number'>2</tspan></text> + <text x='49.375' y='102'><tspan class='Function'>+</tspan></text> + <text x='27.875' y='102'><tspan class='Number'>3</tspan></text> + <text x='17.125' y='121'><tspan class='Function'>√</tspan></text> </g> </g> </g> @@ -351,6 +351,38 @@ <span class='Modifier2'>∘</span><span class='Function'>+</span> <span class='Number'>3</span> <span class='Number'>4</span> </pre> +<svg viewBox='-213 -34 512 134'> + <g font-family='BQN,monospace' font-size='18px'> + <rect class='code' stroke-width='1' rx='10' x='-21.5' y='-24' width='129' height='114'/> + <text><tspan class='Number'>3</tspan> <tspan class='Function'>×</tspan><tspan class='Modifier'>˜</tspan><tspan class='Modifier2'>∘</tspan><tspan class='Function'>+</tspan> <tspan class='Number'>4</tspan></text> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M81.7 1.9V58.9H49.45'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M60.2 1.9V39.9H49.45'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M27.95 1.9V20.9H38.7'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M38.7 20.9V39.9H49.45'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M49.45 39.9V58.9H49.45'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M6.45 1.9V58.9H49.45'/> + <path class='Paren' stroke='currentColor' fill='none' stroke-width='1' d='M49.45 58.9V77.9H-6.987'/> + <g text-anchor='middle'> + <g class='codeCover' stroke-width='6' stroke-linejoin='round'> + <text x='81.625' y='66'>4</text> + <text x='60.125' y='47'>+</text> + <text x='49.375' y='47'>∘</text> + <text x='38.625' y='28'>˜</text> + <text x='27.875' y='28'>×</text> + <text x='6.375' y='66'>3</text> + </g> + <g font-size='15px' opacity='0.9'> + <text x='81.625' y='64'><tspan class='Number'>4</tspan></text> + <text x='60.125' y='45'><tspan class='Function'>+</tspan></text> + <text x='49.375' y='45'><tspan class='Modifier2'>∘</tspan></text> + <text x='38.625' y='26'><tspan class='Modifier'>˜</tspan></text> + <text x='27.875' y='26'><tspan class='Function'>×</tspan></text> + <text x='6.375' y='64'><tspan class='Number'>3</tspan></text> + </g> + </g> + </g> +</svg> + <p>This ordering is more consistent with the fact that the operand of a 1-modifier goes to its left. If we tried going from right to left we'd end up with <code><span class='Function'>×</span><span class='Paren'>(</span><span class='Modifier'>˜</span><span class='Modifier2'>∘</span><span class='Function'>+</span><span class='Paren'>)</span></code>, which uses <code><span class='Modifier'>˜</span></code> as an operand to <code><span class='Modifier2'>∘</span></code>. But a modifier can't be used as an operand. To make it work we'd essentially have to give 1-modifiers a higher precedence than 2-modifiers.</p> <p>In fact, the rules for modifiers are exactly the same as those for functions, but reversed. So why is there a distinction between 1- and 2-modifiers, when for functions we can look to the left to see whether there is a left argument? The reason is that it's natural to follow a 1-modifier by a subject or function that isn't supposed to be its operand. Using an example from the last section, <code><span class='Function'>+</span><span class='Modifier'>˜</span> <span class='Number'>3</span></code> has a subject to the right of the 1-modifier <code><span class='Modifier'>˜</span></code>. Even worse, <code><span class='Function'>+</span><span class='Modifier'>˜</span> <span class='Function'>÷</span> <span class='Number'>3</span></code> looks the same syntactically as <code><span class='Function'>+</span><span class='Modifier2'>∘</span> <span class='Function'>÷</span> <span class='Number'>3</span></code>, but it's two functions <code><span class='Function'>+</span><span class='Modifier'>˜</span></code> and <code><span class='Function'>÷</span></code> applied to <code><span class='Number'>3</span></code> while the version with Atop is a single function <code><span class='Function'>+</span><span class='Modifier2'>∘</span><span class='Function'>÷</span></code> applied to <code><span class='Number'>3</span></code>. So the two-layer system of functions and modifiers forces modifiers to have a fixed number of operands even every function (including those derived by applying modifiers) can be called with one or two arguments.</p> <p>Remember that 1-modifiers are all superscripts? The characters for 2-modifiers use a different rule: each contains an <em>unbroken</em> circle (that is, lines might touch it but not go through it). The 2-modifiers in BQN are the combinators <code><span class='Modifier2'>∘○⊸⟜⌾</span></code>, the sort-of-combinators <code><span class='Modifier2'>⊘◶⍟</span></code>, and the not-at-all-combinators <code><span class='Modifier2'>⎉⚇⎊</span></code>. And the functions that make that unbroken circle rule necessary are written <code><span class='Function'>⌽⍉</span></code>. Since every primitive is a function, 1-modifier, or 2-modifier, you can always tell what type (and role) it has: a superscript is a 1-modifier, an unbroken circle makes it a 2-modifier, and otherwise it's a function.</p> @@ -161,7 +161,10 @@ blobURL ← repoURL∾"/blob/master/" # Environments _getCodeExec ← {𝕗⋄⍎} -_getSvgExec ← {𝕗⋄JoinLines⍟(1<≡)∘(⟨"svg.bqn","⍎"⟩ •Import "dzref")} +_getSvgExec ← {𝕗 + Compile ← (↕62)⊸(•Import "src/c.bqn") # for tutorial/evalexp.bqn + JoinLines⍟(1<≡)∘(⟨"svg.bqn","⍎"⟩ •Import "dzref") +} ################################ diff --git a/tutorial/evalexp.bqn b/tutorial/evalexp.bqn index 17c8c0db..f25144ac 100644 --- a/tutorial/evalexp.bqn +++ b/tutorial/evalexp.bqn @@ -15,25 +15,39 @@ Shadow ← { } DrawEval←{ - ix←𝕩⊏˜i←/𝕩≠' ' - f←0=b←(op←'('=ix)-')'=ix - l←op<<⟜«fn←ix∊"+-×÷⋆√" - g←⍋+`b - ei←¯1∾˜b{((𝕨<0)/𝕩)⌾((𝕨>0)⊸/)𝕩}○(g⊸⊏)»+`f - o←ei⊏˜f/↕∘≠⊸-⌾(g⊸⊏)(1+»l)(⊢+fn×-)1-2×l - g⊏˜↩⍋g⊏l - rev←⍋+`¯1↓(¯1∾g)(⊣⍋⊸⊏⊏˜⟜⍋¬⊏˜)⍋+`⊸+1∾g⊏l∨op - m←1+⌈´d←+`⊸×⌾(rev⊸⊏)fn + b‿const‿blk‿i ← Compile 𝕩 + ba‿bc‿bo‿bp ← '0'-˜⟨ # For each instruction, number of: + "11111000000000010000022000" # Arguments + "000//232323223102303200121" # Stack values consumed + "11111111111111011101111111" # Stack values output + "00000110101000001101000100" # Position determiner + ⟩ + m ← { # Mask of instruction starts + a ← ba(⊣⊏˜≠⊸>×⊢)b + na← ∾⟜≠ (≠-(1+↕∘≠)⊸(»·⌈`×)⌾⌽) <⟜128 b + n ← 1+{(𝕩=⌜a) +˝∘× >⊏⟜na⍟𝕩↕≠a}↕3 + ! ∧´ ↕∘≠⊸< n + Se←{(⊏˜𝕨)Se 1¨⌾((𝕩/𝕨)⊸⊏)𝕩}⍟(0=¯1⊑⊢) + (≠↑∾⟜≠Se 1∾0¨) n + } + mb‿mi ← m⊸/¨ b‿i + mi↓˜↩¯1 + + r←+`(mb⊏bo)-na←mb⊏bc + ! 1=¯1⊑r + p←((¯1↓r)⍋⊸⊏○⍋(⊏⟜r+⊒))⊸⊏/na + j←¯1↓mi⊏˜⊏˜⍟≠{s←𝕩⊏˜g←⍋𝕩⋄(g/˜(⊒s)=s⊏mb⊏bp)⌾((⍷s)⊸⊏)↕≠mb}p + je←j∾¯1.25 + d←+`⊸×f←0<na + f↑˜↩≠p + q←(/f∨j≠p⊏je) (⊏≍⊣) p - pt ← f/⍉> wh×⟨i,d⟩ - off← (o ⊏ ∾⟜(whׯ1.25‿m))⊸- pt - pd ← pt (<(wh×0.6‿0.1)⊸+)⊸∾⟜⌽˘ off - dim← (wh×⟨≠𝕩,2+m⟩)+2‿0×pad - tp ← <˘pt+to+⎉1(0‿1×⌜˜f/¬fn)×off + pd ← <⊸∾⟜⌽˘˜˝ q ⊏ ⍉wh×0.6‿0.1+je≍d + dim← (wh×⟨≠𝕩,2+⌈´d⟩)+2‿0×pad (512‿0⊸⌈⊸(⊣∾˜(t+pad)-˜-˜÷2˙)dim+2×t) SVG gr Enc ∾⥊¨⟨ <"rect" Elt rc∾(Pos-pad)∾"width"‿"height"≍˘FmtNum¨dim <"text" Enc Highlight 𝕩 - (<"path" Elt ps∾"d"≍○<·∾"Mvh"∾⟜Fmt¨⊢)˘ pd - <tp Shadow f/ix + (<"path" Elt ps∾"d"≍○<·∾"MVH"∾⟜Fmt¨⊢)˘ pd + mi ((to+wh×≍)¨Shadow⊏⟜𝕩)⟜(⊏⟜d)○((¬f)⊸/) p ⟩ } diff --git a/tutorial/expression.md b/tutorial/expression.md index 19db15fc..018be7a8 100644 --- a/tutorial/expression.md +++ b/tutorial/expression.md @@ -197,6 +197,10 @@ It's past time we covered how the syntax for modifiers works. Remember how I tol ∘+ 3 4 +<!--GEN +DrawEval "3 ט∘+ 4" +--> + This ordering is more consistent with the fact that the operand of a 1-modifier goes to its left. If we tried going from right to left we'd end up with `×(˜∘+)`, which uses `˜` as an operand to `∘`. But a modifier can't be used as an operand. To make it work we'd essentially have to give 1-modifiers a higher precedence than 2-modifiers. In fact, the rules for modifiers are exactly the same as those for functions, but reversed. So why is there a distinction between 1- and 2-modifiers, when for functions we can look to the left to see whether there is a left argument? The reason is that it's natural to follow a 1-modifier by a subject or function that isn't supposed to be its operand. Using an example from the last section, `+˜ 3` has a subject to the right of the 1-modifier `˜`. Even worse, `+˜ ÷ 3` looks the same syntactically as `+∘ ÷ 3`, but it's two functions `+˜` and `÷` applied to `3` while the version with Atop is a single function `+∘÷` applied to `3`. So the two-layer system of functions and modifiers forces modifiers to have a fixed number of operands even every function (including those derived by applying modifiers) can be called with one or two arguments. |
