1 | config = require "./config"
|
2 | kit = require "./kit"
|
3 | {defaultVisitor} = require "./visitor"
|
4 |
|
5 |
|
6 | class Scope
|
7 | constructor: (par,visitor) ->
|
8 | @glob =
|
9 | decls: []
|
10 | @vars = {}
|
11 | @refs = {}
|
12 | @upds = {}
|
13 | @par = par
|
14 | @policy = if @par then par.policy else @createPolicy()
|
15 | @visitor = visitor ? defaultVisitor()
|
16 | @visitor.setCtx(@)
|
17 | @nxt = []
|
18 | @lab = {}
|
19 | @uniqIds = {}
|
20 | @opts = {}
|
21 | @anc = []
|
22 | @anc.push(@par.anc...) if @par
|
23 | @scopes = []
|
24 | @ids = {}
|
25 | @uids = []
|
26 |
|
27 | updateVisitor: ->
|
28 | @visitor = @visitor.update(@)
|
29 | @
|
30 |
|
31 | subScope: ->
|
32 | subvisitor = @visitor.subScope()
|
33 | return unless subvisitor?
|
34 | new Scope(@,subvisitor)
|
35 |
|
36 | uniqId: (p) ->
|
37 | c = @uniqIds[p] ? 0
|
38 | @uniqIds[p] = c + 1
|
39 | c = "" unless c
|
40 | res = kit.id("#{p}#{c}")
|
41 | res.$dm$orig = p
|
42 | @uids.push res
|
43 | res
|
44 |
|
45 | commitIds: ->
|
46 | for i in @uids
|
47 | if @ids[i.name]
|
48 | loop
|
49 | c = @uniqIds[i.$dm$orig]++
|
50 | i.name = "#{i.$dm$orig}#{c}"
|
51 | break unless @ids[i.name]
|
52 | return
|
53 |
|
54 | stmt: (s, lab) ->
|
55 | r = @visitor[s.type]
|
56 | return @visitor.defaultStmt(s).setOrig(s) unless r?
|
57 | @policy.item s, =>
|
58 | r.call(@visitor,s,lab).setOrig(s)
|
59 |
|
60 | expr: (e) ->
|
61 | h = @visitor[e.type]
|
62 | return @pureExprNode(e) unless h?
|
63 | @policy.item e, => h.call(@visitor,e)
|
64 |
|
65 | stmts: (body) ->
|
66 | b = @blockNode()
|
67 | x = 0
|
68 | loop
|
69 | break if x >= body.length
|
70 | i = body[x]
|
71 | s = @stmt(i)
|
72 | o = s.orig
|
73 | if o and o.type is "EmptyStatement"
|
74 | body.splice(x,1)
|
75 | else
|
76 | body[x] = o if o
|
77 | b = b.append(s)
|
78 | ++x
|
79 | return b
|
80 |
|
81 | prog: (p) ->
|
82 | @policy.scope => @_prog(p)
|
83 | _prog: (p) ->
|
84 | @root = controlNode = @controlNode("scope")
|
85 | @root.label = @uniqId "root"
|
86 | prog = @node = @stmts(p.body)
|
87 | return p if @visitor.noChanges
|
88 | node = @tryCatchNode().setBody(controlNode)
|
89 | controlNode.setBody(prog)
|
90 | node.fwdPass({})
|
91 | controlNode.propagateEff() if @policy.opts.compile is "always"
|
92 | node.backPass({})
|
93 | @calcDone = true
|
94 | @node = node
|
95 | res = []
|
96 | if @thisVar?
|
97 | res.push({
|
98 | type:"VariableDeclaration"
|
99 | kind: "var"
|
100 | declarations: [{
|
101 | type:"VariableDeclarator"
|
102 | id: @thisVar
|
103 | init: {type: "ThisExpression"}
|
104 | }]})
|
105 | res.push(@glob.decls...)
|
106 | body = node.getFullBlock(node.eff)
|
107 | res.push(body...)
|
108 | @eff = node.eff
|
109 | @commitIds()
|
110 | kit.block res
|
111 |
|
112 | module.exports = {Scope}
|
113 |
|