names ← {expr←0} ##.externs dfn ⍝ External references from dfn ⍵. By default, [externs] takes the _name_ of a dfn and returns a vector of the non- local names it references. If left argument [expr] is set, the right argument character vector is taken to be an expression, rather than a function name. externs'test' ⍝ external references from function "test" ┌───────┬────┬─────────┐ │scripts│disp│timestamp│ └───────┴────┴─────────┘ 1 externs'sum←⍵ ⋄ sum÷num' ⍝ external references from expression ┌───┐ │num│ └───┘ See also →fnrefs←, which does a better job for tradfns but not so well for dfns. Technical notes: [externs] uses 60⌶ to produce a nested vector of token vectors for the subject function ⍵. sample←{ ⍝ sample succ←{1+⍵} pred←{⍵-1} (aaa ccc)←⍺ ⍵ aaa+bbb×succ pred ccc } 60⌶⎕nr'sample' ┌─────────────────────┬──────────────────┬──────────────────┬───────────────────┬───────────────────────────┬───┐ │┌──────┬─┬─┬────────┐│┌────┬─┬─┬─┬─┬─┬─┐│┌────┬─┬─┬─┬─┬─┬─┐│┌─┬───┬───┬─┬─┬─┬─┐│┌───┬─┬───┬─┬────┬────┬───┐│┌─┐│ ││sample│←│{│⍝ sample│││succ│←│{│1│+│⍵│}│││pred│←│{│⍵│-│1│}│││(│aaa│ccc│)│←│⍺│⍵│││aaa│+│bbb│×│succ│pred│ccc│││}││ │└──────┴─┴─┴────────┘│└────┴─┴─┴─┴─┴─┴─┘│└────┴─┴─┴─┴─┴─┴─┘│└─┴───┴───┴─┴─┴─┴─┘│└───┴─┴───┴─┴────┴────┴───┘│└─┘│ └─────────────────────┴──────────────────┴──────────────────┴───────────────────┴───────────────────────────┴───┘ [clean] takes these tokens vectors and joins them into a single vector of tokens with diamonds between the lines. In addition, "comment" tokens and parenthesis tokens are removed. For the purposes of extern's analysis, the nesting of names to the left of an assignment arrow (such(as this))← is irrlevant and can be ig- nored. clean toks ┌──────┬─┬─┬─┬────┬─┬─┬─┬─┬─┬─┬─┬────┬─┬─┬─┬─┬─┬─┬─┬───┬───┬─┬─┬─┬─┬───┬─┬───┬─┬────┬────┬───┬─┬─┐ │sample│←│{│⋄│succ│←│{│1│+│⍵│}│⋄│pred│←│{│⍵│-│1│}│⋄│aaa│ccc│←│⍺│⍵│⋄│aaa│+│bbb│×│succ│pred│ccc│⋄│}│ └──────┴─┴─┴─┴────┴─┴─┴─┴─┴─┴─┴─┴────┴─┴─┴─┴─┴─┴─┴─┴───┴───┴─┴─┴─┴─┴───┴─┴───┴─┴────┴────┴───┴─┴─┘ There may be a small performance gain to be had, at the expense of a little add- itional complexity, by having [clean] remove surplus diamond tokens. ⋄ ⋄ → ⋄ ─┐ ⋄ } → } ├─ surplus diamond removal ( ⋄ → { ─┘ rmsd←{(⍺⍺~(,¨⍺)⍷⍵)/⍵} ⍝ without surplus diamonds rmdd←'⋄⋄'∘(⊢rmsd) ⍝ ⋄⋄ → ⋄ rmdb←'⋄}'∘(⊢rmsd) ⍝ ⋄} → } rmbd←'{⋄'∘((¯1∘⌽)rmsd) ⍝ {⋄ → { [nest] folds the tokens vector so that inner dfns become items of their contain- ing outer functions. ┌──────┬─┬─────────────────────────────────────────────────────────────────────────────────┐ │sample│←│┌─┬────┬─┬───────┬─┬────┬─┬───────┬─┬───┬───┬─┬─┬─┬─┬───┬─┬───┬─┬────┬────┬───┬─┐│ │ │ ││⋄│succ│←│┌─┬─┬─┐│⋄│pred│←│┌─┬─┬─┐│⋄│aaa│ccc│←│⍺│⍵│⋄│aaa│+│bbb│×│succ│pred│ccc│⋄││ │ │ ││ │ │ ││1│+│⍵││ │ │ ││⍵│-│1││ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ││ │ │ ││ │ │ │└─┴─┴─┘│ │ │ │└─┴─┴─┘│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ││ │ │ │└─┴────┴─┴───────┴─┴────┴─┴───────┴─┴───┴───┴─┴─┴─┴─┴───┴─┴───┴─┴────┴────┴───┴─┘│ └──────┴─┴─────────────────────────────────────────────────────────────────────────────────┘ [nest] also reorganises token order so that inner dfn items move to the end. This is so that forward references from within such functions are not viewed as external references. A similar techique is used in kind-colouring function →kk←. nest clean toks ⍝ inner dfns moved to the end ┌──────┬─┬─────────────────────────────────────────────────────────────────────────────────┐ │sample│←│┌─┬────┬─┬─┬────┬─┬─┬───┬───┬─┬─┬─┬─┬───┬─┬───┬─┬────┬────┬───┬─┬───────┬───────┐│ │ │ ││⋄│succ│←│⋄│pred│←│⋄│aaa│ccc│←│⍺│⍵│⋄│aaa│+│bbb│×│succ│pred│ccc│⋄│┌─┬─┬─┐│┌─┬─┬─┐││ │ │ ││ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ││1│+│⍵│││⍵│-│1│││ │ │ ││ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │└─┴─┴─┘│└─┴─┴─┘││ │ │ │└─┴────┴─┴─┴────┴─┴─┴───┴───┴─┴─┴─┴─┴───┴─┴───┴─┴────┴────┴───┴─┴───────┴───────┘│ └──────┴─┴─────────────────────────────────────────────────────────────────────────────────┘ Finally, [exts] performs a depth-first traversal of the nested tokens vector, collecting external references. This is achieved with a left-to-right →foldl← reduction, with accumulating left argument tuple (A L G): X Extern names: those still pending at end-of-segment '⋄' or ':' token. L Local names: on finding a '←' token, pending names are moved here. P Pending names encountered in left-to-right traversal. On completion of the depth-first traversal of the whole function, any names re- maining in the X accumulator are judged external and returned as result. Bug: [externs] is confused by some dotted expressions: memo←{ ⍝ Function memoization. ⍺←⊢ ⍝ ambi-valent. (⊂⍺ ⍵ ⍵)∊⍵⍵.keys:⍵⍵.((keys⍳⊂⍺ ⍵ ⍵)⊃vals) ⍝ arg(s) known: fetch result. ↑⍬⍴⍵⍵.(vals keys),∘⊂←(⍺ ⍺⍺ ⍵)(⍺ ⍵ ⍵) ⍝ else: calc & extend cache. } externs'memo' ┌────┐ │vals│ └────┘ Examples: externs'test' ⍝ test refers to scripts, disp and timestamp ┌───────┬────┬─────────┐ │scripts│disp│timestamp│ └───────┴────┴─────────┘ externs'externs' ⍝ externs makes no external references ⍕↑{(×≢¨⍵)/↓⍉↑⍺⍵}∘(externs¨)⍨ ⎕nl -3 4 ⍝ all dfns/ops with extern refs UndoRedo redo ascana ascan cal days date compidn days cxdraw f.Coord defs ⎕SE.Dyalog.Utils.repObj externs esh ratsum index ltov lcase dxb joy nats kk kind tokens memo vals parse disp segs subs rats factors scc dsp ssmat ss ssword words stamps path test scripts disp timestamp von lcase ucase wrapnote vtrim squeeze wrap justify xpower xtimes See also: defs fnrefs Back to: contents Back to: Workspaces