1 | kit = require "./kit"
|
2 | {Scope,ActiveScope} = require "./scope"
|
3 | policy = require "./policy"
|
4 | require "./graph"
|
5 | require "./expr"
|
6 | assert = require "assert"
|
7 | {Visitor, ActiveVisitor, DisabledVisitor} = require "./visitor"
|
8 |
|
9 | isLoop = (stmt) ->
|
10 | stmt.type is "ForStatement"
|
11 |
|
12 | ActiveVisitor::LabeledStatement = (stmt) ->
|
13 | name = stmt.label.name
|
14 | if isLoop(stmt.body)
|
15 | res = @ctx.stmt(stmt.body, name)
|
16 | res.orig = stmt
|
17 | return res
|
18 | old = @ctx.lab
|
19 | block = @ctx.controlNode()
|
20 | @ctx.lab = nlab = Object.create old
|
21 | block.labname = name
|
22 | nlab[name] = {brk:block}
|
23 | block.setLabel("#{name}").setBody(@ctx.stmt(stmt.body, name))
|
24 | @ctx.lab = old
|
25 | return block
|
26 |
|
27 | ActiveVisitor::ContinueStatement = (stmt) ->
|
28 | name = if stmt.label? then stmt.label.name else "#"
|
29 | l = @ctx.lab[name]
|
30 | unless l? and l.cnt?
|
31 | throw new Error("no such label #{name}")
|
32 | l.cnt.breakNode()
|
33 |
|
34 | ActiveVisitor::BreakStatement = (stmt) ->
|
35 | name = if stmt.label? then stmt.label.name else "#"
|
36 | l = @ctx.lab[name]
|
37 | unless l? and l.brk?
|
38 | throw new Error("no such label #{name}")
|
39 | l.brk.breakNode()
|
40 |
|
41 | ActiveVisitor::BlockStatement = (stmt) ->
|
42 | @ctx.stmts(stmt.body)
|
43 |
|
44 | ActiveVisitor::EmptyStatement = (stmt) ->
|
45 | return @ctx.pureNode([stmt])
|
46 |
|
47 | Visitor::ExpressionStatement = (stmt) ->
|
48 | @ctx.expr(stmt.expression).ignoreResult().setOrig(false)
|
49 |
|
50 | ActiveVisitor::IfStatement = (stmt) ->
|
51 | {test:i, consequent: t, alternate: e} = stmt
|
52 | res = @ctx.branchedNode(
|
53 | (t, e) ->
|
54 | stmt.consequent = t
|
55 | stmt.alternate = e
|
56 | stmt
|
57 | stmt).setOrig(stmt)
|
58 | .setDeps(@ctx.stmt(t), if e? then @ctx.stmt(e) else @ctx.emptyNode())
|
59 | @ctx.bindNode(res,[@ctx.expr(i).setPosition([stmt,"test"])])
|
60 |
|
61 | ActiveVisitor::SwitchStatement = (stmt) ->
|
62 | old = @ctx.lab
|
63 | @ctx.lab = nlab = Object.create old
|
64 | res = @ctx.controlNode()
|
65 | nlab["#"] = {brk:res}
|
66 | block = @ctx.blockNode()
|
67 | s = @ctx.sharedNode(@ctx.expr(stmt.discriminant),block)
|
68 | res.setBody(s)
|
69 | for i,x in stmt.cases
|
70 | if i.test?
|
71 | block.append(@IfStatement(kit.ifte(
|
72 | kit.eq(s._ref,i.test),
|
73 | i.consequent)))
|
74 | else
|
75 | block.append(@ctx.stmts i.consequent)
|
76 | res
|
77 |
|
78 | ActiveVisitor::ReturnStatement = (s) ->
|
79 | a = s.argument
|
80 | unless a?
|
81 | return @ctx.root.breakNode()
|
82 | @ctx.root.breakNode(@ctx.expr a)
|
83 |
|
84 | Visitor::postDecl = (stmt) ->
|
85 | @ctx.pureNode([stmt])
|
86 |
|
87 | ActiveVisitor::postDecl = (stmt) ->
|
88 | @ctx.glob.decls.push(stmt)
|
89 | @ctx.emptyNode()
|
90 |
|
91 | Visitor::FunctionDeclaration = (stmt) ->
|
92 | ctx = @ctx.subScope(stmt)
|
93 | if stmt.params?
|
94 | ctx.vars[i.name] = true for i in stmt.params when i.name
|
95 | return @ctx.pureNode([stmt]) unless ctx?
|
96 | ctx.policy = @policy
|
97 | stmt.body = ctx.prog stmt.body
|
98 | if stmt.generator
|
99 | stmt.generator = false
|
100 | @ctx.refs[i] = true for i, v of ctx.upds when v and not ctx.vars[i]
|
101 | @postDecl(stmt)
|
102 |
|
103 | Visitor::VariableDeclaration = (stmt) ->
|
104 | for i in stmt.declarations when i.init
|
105 | @policy.nameDetails(i.id,"=")
|
106 | en = @ctx.expr(i.init)
|
107 | assert.ok(en.pureExpr?)
|
108 | i.init = en.pureExpr
|
109 | return @ctx.pureNode([stmt])
|
110 |
|
111 | ActiveVisitor::VariableDeclaration = (stmt) ->
|
112 | cur = @ctx.emptyNode()
|
113 | declarations = []
|
114 | orig = []
|
115 | for i in stmt.declarations
|
116 | @ctx.vars[i.id.name] = true
|
117 | @ctx.ids[i.id.name] = true unless i.id.$dm$orig
|
118 | declarations.push {type: "VariableDeclarator", id: i.id}
|
119 | if @policy.opts.varCapt is false
|
120 | @ctx.refs[i.id.name] = true
|
121 | if i.init?
|
122 | asgn = kit.assign(i.id,i.init)
|
123 | e = @ctx.stmt(kit.exprStmt(asgn))
|
124 | cur = cur.append(e)
|
125 | orig.push(asgn)
|
126 | @ctx.glob.decls.push {type:"VariableDeclaration",declarations,kind: "var"}
|
127 | if cur.pureBlock?
|
128 | cur.setOrig(kit.block(cur.pureBlock()))
|
129 | else
|
130 | cur.setOrig(kit.exprStmt(kit.seqExpr(orig...)))
|
131 | cur
|
132 |
|
133 | ActiveVisitor::ForStatement = (stmt, label) ->
|
134 | wbody = []
|
135 | {init,test,update,body} = stmt
|
136 | test ?= kit.lit(true)
|
137 | if init?
|
138 | if init.type is "VariableDeclaration"
|
139 | wbody.push init
|
140 | exprs = []
|
141 | for i in init.declarations when i.init
|
142 | exprs.push(kit.assign(i.id, i.init))
|
143 | stmt.init = kit.seqExpr exprs...
|
144 | else
|
145 | wbody.push(kit.exprStmt(init))
|
146 | lexpr = {type:"WhileStatement",test,body:body,$dm$update:update}
|
147 | if label?
|
148 | lexpr = {type: "LabeledStatement", body: lexpr, label: kit.id(label)}
|
149 | wbody.push(lexpr)
|
150 | return @ctx.stmts(wbody)
|
151 |
|
152 | wrapP = (nowrap, v) ->
|
153 | if nowrap then v else kit.call(kit.packId("p"),[v])
|
154 |
|
155 | rewriteForIter = (itername, stmt, label, nowrap) ->
|
156 | {left,right,body} = stmt
|
157 | iterName = @ctx.uniqId("iter")
|
158 | iterCtr = kit.call(kit.packId(itername),[right])
|
159 | init = wrapP(nowrap, iterCtr)
|
160 | iterDecl = {type:"VariableDeclarator",id:iterName,init}
|
161 | resDecls = [iterDecl]
|
162 | init = {type: "VariableDeclaration", kind: "var", declarations: resDecls}
|
163 | if left.type is "VariableDeclaration"
|
164 | throw new Error("NOT IMPLEMENTED") unless left.declarations.length is 1
|
165 | stmt.left = pat = left.declarations[0].id
|
166 | @ctx.glob.decls.push left
|
167 | else
|
168 | pat = left
|
169 | body = kit.flatBlock(kit.exprStmt(
|
170 | kit.assign(pat,kit.mem(iterName,kit.id("value")))),body)
|
171 | update = kit.assign(iterName, wrapP(nowrap,kit.call(iterName,[])))
|
172 | [{type:"ForStatement",init,test:iterName,update,body},iterCtr]
|
173 |
|
174 | commonForIter = (itername, stmt, label) ->
|
175 | [b,iterCtr] = rewriteForIter.call(@,itername,stmt,label)
|
176 | bn = @ForStatement(b, label)
|
177 | @ctx.bindNode(bn,[@ctx.expr(stmt.right).setPosition([iterCtr.arguments,0])])
|
178 |
|
179 | ActiveVisitor::ForInStatement = (stmt, label) ->
|
180 | commonForIter.call(@, "forInIterator", stmt, label)
|
181 |
|
182 | ActiveVisitor::ForOfStatement = (stmt, label) ->
|
183 | name = if @policy.opts.varCapt is false then "iterator" else "iteratorBuf"
|
184 | b = commonForIter.call(@, name, stmt, label)
|
185 | unless @policy.opts.keepForOf
|
186 | [orig] = rewriteForIter.call(@, "iterator", stmt, label, true)
|
187 | b.setOrig(orig)
|
188 | b
|
189 |
|
190 | commonWhile = (pre) ->
|
191 | (stmt, label) ->
|
192 | {test,body} = stmt
|
193 | bexpr = kit.ifte test, [], []
|
194 | loopBranch = @ctx.branchedNode(
|
195 | (c,a) ->
|
196 | bexpr.consequent = kit.flatBlock c
|
197 | bexpr.alternate = kit.flatBlock a if a?
|
198 | bexpr
|
199 | bexpr)
|
200 | update = stmt.$dm$update
|
201 | upd = @ctx.expr(update).ignoreResult() if update?
|
202 | brkControl = @ctx.loopNode()
|
203 | cntControl = @ctx.controlNode()
|
204 | if label?
|
205 | brkControl.setLabel("#{label}Brk")
|
206 | cntControl.setLabel("#{label}Cont")
|
207 | else
|
208 | brkControl.setLabel("brk")
|
209 | cntControl.setLabel("cont")
|
210 | old = @ctx.lab
|
211 | @ctx.lab = nlab = Object.create old
|
212 | labDef = {brk:brkControl,cnt:cntControl}
|
213 | nlab["#"] = labDef
|
214 | nlab[label] = labDef if label?
|
215 | bodyNode = @ctx.stmtNode(body)
|
216 | bodyv = if pre
|
217 | testNode = @ctx.expr(test).setPosition([bexpr,"test"])
|
218 | @ctx.bindNode(
|
219 | loopBranch.setDeps(
|
220 | bodyNode
|
221 | brkControl.breakNode())
|
222 | [testNode])
|
223 | else
|
224 | bexpr.test = test = kit.not(test)
|
225 | testNode = @ctx.expr(test).setPosition([bexpr,"test"])
|
226 | @ctx.blockNode().append(
|
227 | bodyNode
|
228 | @ctx.bindNode(
|
229 | loopBranch.setDeps(brkControl.breakNode(),@ctx.emptyNode())
|
230 | [testNode]))
|
231 | @ctx.lab = old
|
232 | if label?
|
233 | bodyv.name ?= @ctx.uniqId "{label}Loop"
|
234 | inner = cntControl.setBody(bodyv)
|
235 | inner = inner.append(upd) if upd?
|
236 | brkControl.test = testNode
|
237 | brkControl.inner = bodyNode
|
238 | brkControl.update = upd ? @ctx.emptyNode()
|
239 | brkControl.pre = pre
|
240 | brkControl.cont = cntControl
|
241 | brkControl.setBody(@ctx.repeatNode(inner))
|
242 |
|
243 | ActiveVisitor::WhileStatement = commonWhile(true)
|
244 | ActiveVisitor::DoWhileStatement = commonWhile()
|
245 |
|
246 | ActiveVisitor::ThrowStatement = (stmt) ->
|
247 | e = stmt.argument
|
248 | ea = @ctx.expr e
|
249 | @ctx.throwNode ea
|
250 |
|
251 | ActiveVisitor::TryStatement = (stmt) ->
|
252 | {block,handler,finalizer} = stmt
|
253 | res = @ctx.tryCatchNode().setBody(@ctx.stmt(block))
|
254 | res.setFin(@ctx.stmt(finalizer)) if finalizer?
|
255 | if handler?
|
256 | res.setHandler(handler.param,@ctx.stmt(handler.body))
|
257 | res
|
258 |
|
259 | ActiveVisitor::WithStatement = (stmt) ->
|
260 | res = @ctx.branchedNode(
|
261 | (b) ->
|
262 | stmt.body = b
|
263 | stmt
|
264 | stmt).setOrig(stmt).setDeps(@ctx.stmt(stmt.body))
|
265 | @ctx.bindNode(res,[@ctx.expr(stmt.object).setPosition([stmt,"object"])])
|
266 |
|
267 | Visitor::defaultStmt = (stmt) -> @ctx.pureNode([stmt])
|
268 |
|