UNPKG

2.86 kBtext/coffeescriptView Raw
1config = require "./config"
2kit = require "./kit"
3{defaultVisitor} = require "./visitor"
4
5# stores information about translating scope (function body or top)
6class 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 # replaces current visitor if current policy requests it
27 updateVisitor: ->
28 @visitor = @visitor.update(@)
29 @
30 # new scope for a function definition inside this scope
31 subScope: ->
32 subvisitor = @visitor.subScope()
33 return unless subvisitor?
34 new Scope(@,subvisitor)
35 # returns unique identifier for current nodes
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 # removes identifier duplicates
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 # convert statement with optional label
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 # converts expression with
60 expr: (e) ->
61 h = @visitor[e.type]
62 return @pureExprNode(e) unless h?
63 @policy.item e, => h.call(@visitor,e)
64 # converts list of statements
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 # entry point for conversion
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
112module.exports = {Scope}
113