See attached WS.
#!/usr/local/bin/apl --script
 ⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝
⍝
⍝ dbl-check-2.apl 2016-07-11 21:42:51 (GMT-7)
⍝
 ⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝

∇z←pkg⍙alp
 z←'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
∇
∇z←pkg⍙dig
 z←'1234567890'
∇
∇z←pkg⍙empty_string text;m
 ⍝ Remove content from quoted string, leaving only a pair of quotes.
 ⍝ This is useful to hide quoted text from analysis.
 z←((¯1⌽m)∨m←~≠\text='''')/text
 z←(~2↓(m,0 0)∧(0 0,m←z=''''))/z
∇
∇z←(pred pkg⍙filter1) list
 ⍝ Filter items of list according to unary predicate.
 z←(,⊃pred¨list)/list
∇

∇z←pkg⍙function_refs func;labels;name;locals;tokens;ids
 ⍝ For a function expressed as a list of lines, return a list of all
 ⍝ nonlocal names used in the function.
 z←labels←⍬
 (name locals)←pkg⍙header_info pkg⍙parse 1⊃func
 more:
 func←1↓func
 →(0=⍴func)/done
 tokens←pkg⍙parse pkg⍙empty_string pkg⍙strip_comment 1⊃func
 ids←pkg⍙is_id pkg⍙filter1 tokens
 ids←(~ids∊locals)/ids
 labels←labels,pkg⍙label tokens
 z←z,ids
 →more
 done:
 z←∪z~labels
∇

∇z←pkg⍙header_info tokens;queue;locals;t;op;name
 ⍝ Given a parsed function or operator header line, return the
 ⍝ function or operator name and a list of local variable names.
 ⍝
 ⍝ z←foo;locals
 ⍝ z←foo b;locals
 ⍝ z←a foo b;locals
 ⍝ z←(x foo);locals
 ⍝ z←(x foo) b;locals
 ⍝ z←(x foo y);locals
 ⍝ z←(x foo y) b;locals
 ⍝ z←a (x foo) b;locals
 ⍝ z←a (x foo y) b;locals
 queue←locals←name←⍬
 op←0
 more:
 →(0=⍴tokens)/end
 t←1⊃tokens
 tokens←1↓tokens
 →('←'∊t)/assign
 →('('∊t)/op_start
 →((')'∊t)∧(op=1))/op_end
 →(';'∊t)/locals_list
 ⍎(pkg⍙is_id t)/'queue←queue,⊂t'
 →more
 assign:
 locals←locals,queue
 queue←⍬
 →more
 op_start:
 locals←locals,queue
 queue←⍬
 op←1
 →more
 op_end:
 locals←locals,⊂1⊃queue
 name←2⊃queue
 ⍎(3=⍴queue)/'locals←locals,⊂3⊃queue'
 queue←⍬
 →more
 locals_list:
 ⍎(pkg⍙is_id t)/'locals←locals,⊂t'
 →(0=⍴tokens)/end
 t←1⊃tokens
 tokens←1↓tokens
 →locals_list
 end:
 →(0≠⍴name)/out
 ⍎(1=⍴queue)/'name←1⊃queue ◊ queue←⍬'
 ⍎(2=⍴queue)/'name←1⊃queue ◊ queue←1↓queue'
 ⍎(3=⍴queue)/'name←2⊃queue ◊ queue←1 0 1/queue'
 out:
 z←name (locals,queue)
∇

∇z←pkg⍙id1
 z←'⎕∆⍙_'
∇

∇z←pkg⍙idX
 z←'∆⍙_¯'
∇

∇z←pkg⍙is_id token
 ⍝ Return true if token is a valid identifier.
 z←((1↑,token)∊pkg⍙id1,pkg⍙alp)∧(∧/(1↓,token)∊pkg⍙idX,pkg⍙alp,pkg⍙dig)
∇

∇z←pkg⍙label tokens
 ⍝ Given a parsed function line, return the name of a label which
 ⍝ appears on that line.
 z←(1⌽∨/¨':'=¨tokens)/tokens
∇

∇z←pkg⍙nu1
 z←'¯'
∇

∇z←pkg⍙nuX
 z←'JE¯.'
∇

∇z←pkg⍙parse text;c;i;n;f
 ⍝ Parse text into a list of identifiers and interstital text. Note
 ⍝ that the interstitial text preserves blanks; this is useful when we
 ⍝ want to rewrite the identifiers in a text without changing the
 ⍝ layout.
 z←c←⍬
 i←n←0
 more:
 →(0=⍴text)/done
 f←1↑text
 text←1↓text
 →((f∊pkg⍙nuX,pkg⍙dig)∧(n=1))/accum
 →(((f∊pkg⍙idX,pkg⍙alp,pkg⍙dig)∧(i=1))∨((f∊pkg⍙nuX,pkg⍙dig)∧(n=1)))/accum
 →((f∊pkg⍙id1,pkg⍙alp)∧(i=0))/start_id
 →((f∊pkg⍙nu1,pkg⍙dig)∧(i=0)∧(n=0))/start_num
 ⍎((0≠⍴c)∧(i=1)∨(n=1))/'z←z,⊂c ◊ c←⍬'
 i←n←0
 →accum
 start_id:
 i←1
 →flush
 start_num:
 n←1
 flush:
 ⍎(0≠⍴c)/'z←z,⊂c ◊ c←⍬'
 accum:
 c←c,f
 →more
 done:
 z←z,⊂c
∇

∇pkg⍙refresh_fn_refs;ft;all;outdated;fdef;times;fn;fns;names;i;entry;new;refs
 ⍝ Refresh pkg⍙⍙fn_refs_cache.
 ft←0=⍴pkg⍙⍙fn_refs_cache
 ⍎(ft)/'⎕←⊂''Building complete function references cache...'''
 all←pkg⍙⍙strip_trailing_blanks¨⊂[2]⎕nl 3 4
 →(0=⍴pkg⍙⍙fn_refs_cache)/add_new
 ⍝ Remove deleted
 pkg⍙⍙fn_refs_cache←(~(1⊃¨pkg⍙⍙fn_refs_cache)∊⊂¨all)/pkg⍙⍙fn_refs_cache
 ⍝ Update changed
 →(0=⍴pkg⍙⍙fn_refs_cache)/add_new
 outdated←⍬
 names←1⊃¨pkg⍙⍙fn_refs_cache
 times←2⊃¨pkg⍙⍙fn_refs_cache
 fns←all
 more1: →(0=⍴fns)/update
 fn←↑fns
 fns←1↓fns
 i←names⍳⊂fn
 →(i>⍴names)/more1
 →(times[i]≡⊂2 ⎕at fn)/more1
 outdated←outdated,⊂fn
 →more1
 update:
 names←1⊃¨pkg⍙⍙fn_refs_cache
 pkg⍙⍙fn_refs_cache←(~names∊outdated)/pkg⍙⍙fn_refs_cache
 more2: →(0=⍴outdated)/add_new
 fn←↑outdated
 outdated←1↓outdated
 fdef←⊂[2]⎕cr fn
 →(0=⍴fdef)/more2
 entry←⊂(fn) (2 ⎕at fn) ((⊂⍋⊃refs)⌷refs←pkg⍙function_refs fdef)
 pkg⍙⍙fn_refs_cache←pkg⍙⍙fn_refs_cache,entry
 →more2
 ⍝ Add new
 add_new:
 new←all
 →(0=⍴pkg⍙⍙fn_refs_cache)/more3
 new←(~all∊1⊃¨pkg⍙⍙fn_refs_cache)/all
 more3: →(0=⍴new)/done
 fn←↑new
 new←1↓new
 fdef←⊂[2]⎕cr fn
 →(0=⍴fdef)/more3
 entry←⊂(fn) (2 ⎕at fn) ((⊂⍋⊃refs)⌷refs←pkg⍙function_refs fdef)
 pkg⍙⍙fn_refs_cache←pkg⍙⍙fn_refs_cache,entry
 →more3
 done:
 ⍎(ft)/'⎕←⊂''Done. Updates will be done incrementally.'' ◊ ⎕←'''''
∇

∇z←pkg⍙strip_comment text
 ⍝ Strip an APL comment from text.
 z←(~∨\(text='⍝')>≠\text='''')/text
∇

∇z←pkg⍙⍙strip_trailing_blanks v
 ⍝ Strip trailing blanks from a string.
 v←∊v
 z←(~⌽∧\' '=⌽⊃v)/⊃v
∇

pkg⍙⍙fn_refs_cache←0 ⍝ prototype...
  pkg⍙⍙fn_refs_cache←0⍴pkg⍙⍙fn_refs_cache

pkg⍙refresh_fn_refs

)check

Reply via email to