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