UNPKG

8.18 kBtext/coffeescriptView Raw
1kit = require "./kit"
2{Scope,ActiveScope} = require "./scope"
3policy = require "./policy"
4require "./graph"
5require "./expr"
6assert = require "assert"
7{Visitor, ActiveVisitor, DisabledVisitor} = require "./visitor"
8
9isLoop = (stmt) ->
10 stmt.type is "ForStatement"
11
12ActiveVisitor::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
27ActiveVisitor::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
34ActiveVisitor::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
41ActiveVisitor::BlockStatement = (stmt) ->
42 @ctx.stmts(stmt.body)
43
44ActiveVisitor::EmptyStatement = (stmt) ->
45 return @ctx.pureNode([stmt])
46
47Visitor::ExpressionStatement = (stmt) ->
48 @ctx.expr(stmt.expression).ignoreResult().setOrig(false)
49
50ActiveVisitor::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
61ActiveVisitor::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
78ActiveVisitor::ReturnStatement = (s) ->
79 a = s.argument
80 unless a?
81 return @ctx.root.breakNode()
82 @ctx.root.breakNode(@ctx.expr a)
83
84Visitor::postDecl = (stmt) ->
85 @ctx.pureNode([stmt])
86
87ActiveVisitor::postDecl = (stmt) ->
88 @ctx.glob.decls.push(stmt)
89 @ctx.emptyNode()
90
91Visitor::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
103Visitor::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
111ActiveVisitor::VariableDeclaration = (stmt) ->
112 cur = @ctx.emptyNode()
113 declarations = []
114 orig = []
115 for i in stmt.declarations
116 @ctx.vars[i.id.name] = true #TODO: ES6
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
133ActiveVisitor::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
152wrapP = (nowrap, v) ->
153 if nowrap then v else kit.call(kit.packId("p"),[v])
154
155rewriteForIter = (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
174commonForIter = (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
179ActiveVisitor::ForInStatement = (stmt, label) ->
180 commonForIter.call(@, "forInIterator", stmt, label)
181
182ActiveVisitor::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
190commonWhile = (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
243ActiveVisitor::WhileStatement = commonWhile(true)
244ActiveVisitor::DoWhileStatement = commonWhile()
245
246ActiveVisitor::ThrowStatement = (stmt) ->
247 e = stmt.argument
248 ea = @ctx.expr e
249 @ctx.throwNode ea
250
251ActiveVisitor::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
259ActiveVisitor::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
267Visitor::defaultStmt = (stmt) -> @ctx.pureNode([stmt])
268