UNPKG

6.84 kBtext/coffeescriptView Raw
1kit = module.exports = {}
2config = require "./config"
3escodegen = require "escodegen"
4assert = require "assert"
5esutils = require "esutils"
6esast = esutils.ast
7
8kit.block = mkBlock = (args) ->
9 return args[0] if args.length is 1 and args[0].type is "BlockStatement"
10 body = if Array.isArray args then args else [args]
11 for i in body
12 assert.ok(i.type?)
13 {type:"BlockStatement",body}
14
15kit.flatBlock = mkFlatBlock = (args...) ->
16 return null unless args.length
17 body = []
18 flatten = (cur) ->
19 if Array.isArray cur
20 for i in cur
21 flatten i
22 else if cur.type is "BlockStatement"
23 flatten cur.body
24 else
25 body.push cur
26 flatten(args)
27 return null unless body.length
28 return body[0] if body.length is 1
29 for i in body
30 assert.ok(i.type?)
31 {type:"BlockStatement",body}
32
33kit.blockStmts = (stmt) ->
34 return stmt.body if stmt.type is "BlockStatement"
35 [stmt]
36
37kit.ret = mkReturn = (argument) ->
38 {type:"ReturnStatement",argument}
39
40kit.call = (callee,args) ->
41 callee = kit.id(callee) if callee.substr?
42 {type:"CallExpression",callee,arguments:args}
43
44kit.id = mkId = (name) -> {type:"Identifier",name}
45
46kit.varDecl = (n, v) ->
47 {
48 type:"VariableDeclaration", kind: "var",
49 declarations:[{
50 type: "VariableDeclarator"
51 id: n
52 init: v
53 }]}
54
55kit.packId = packId = (id) ->
56 p = config.packageVar
57 return id unless p?
58 kit.mem (mkId p), (mkId id)
59
60kit.spread = (fun) ->
61 return kit.call(kit.packId("spread"),[fun])
62
63kit.spreadFun = (args, fun) ->
64 if args.length is 1
65 if fun.$dm$argNum? and fun.$dm$argNum > 1 or
66 fun.params? and fun.params.length > 1
67 return kit.spread(fun)
68 return fun
69 return fun if args.length is 0
70 return kit.spread(fun)
71
72kit.spreadApp = (args, fun) ->
73 fun = kit.spreadFun(args, fun)
74 return [kit.pure(),fun] if args.length is 0
75 return [args[0],fun] if args.length is 1
76 return [kit.arrM(args),fun]
77
78kit.halt = mkHalt = -> kit.call(kit.id("halt"),[])
79
80kit.ifte = mkIf = (test,consequent,alternate) ->
81 consequent = mkFlatBlock consequent
82 if alternate?
83 alternate = mkFlatBlock alternate
84 if alternate? and alternate.body? and alternate.body.length is 0
85 alternate = null
86 consequent = {type:"BlockStatement",body:[]} unless consequent?
87 {type:"IfStatement",test,consequent,alternate}
88
89{noThisNeeded} = config
90noThisNeeded ?= {}
91
92# NOTE: this will only work if callee doesn't need `this`
93kit.matchEta = (p,b) ->
94 x = matchSingleCallBlock b.body
95 return unless x?
96 c = x.callee
97 if c.type is "MemberExpression"
98 return unless c.object.type is "Identifier" and
99 (noThisNeeded[c.object.name] or c.object.name is config.packageVar)
100 else
101 return unless c.type is "Identifier"
102 a = x.arguments
103 return if p.length < a.length
104 for j,s in a
105 i = p[s]
106 return unless i.type is j.type and j.type is "Identifier"
107 return unless i.name is j.name
108 x.callee.$dm$argNum = p.length
109 return x.callee
110
111matchSingleCallBlock = (x) ->
112 return unless x.length is 1
113 x = x[0]
114 return unless x.type is "ReturnStatement"
115 x = x.argument
116 return unless x?
117 return unless x.type is "CallExpression"
118 return x
119
120kit.fun = mkFun = (params, stmt) ->
121 stmt = mkBlock stmt
122 eta = kit.matchEta params, stmt
123 return eta if eta?
124 {type:"FunctionExpression",params,body:stmt}
125
126kit.lit = mkLit = (v) -> {type:"Literal",value: v}
127
128kit.coerce = (v) -> kit.call(packId("coerce"),[mkFun([],v)])
129
130kit.mem = (p...) ->
131 res = p[0]
132 assert.ok(res.type?)
133 for i in p[1..]
134 assert.ok(i.type?)
135 res = {type:"MemberExpression",object:res,property:i}
136 res
137
138kit.not = (argument) ->
139 {type:"UnaryExpression",prefix:true,operator:"!",argument}
140kit.eq = (left, right) ->
141 {type:"BinaryExpression",operator:"===",left,right}
142
143kit.arrM = (args) -> kit.call(kit.packId("arr"), [kit.arr(args)])
144
145kit.mbind = (from, fun) ->
146 assert.ok(Array.isArray(from))
147 [from,fun] = kit.spreadApp(from, fun)
148 assert.ok(fun?)
149 kit.call(kit.mem(from,mkId("mbind")),[fun])
150kit.catch = (from, arg, to) ->
151 args = []
152 args.push arg if arg?
153 return kit.call(kit.mem(from,mkId "mhandle"),[mkFun(args, to)])
154kit.finally = (from, to) ->
155 return kit.call(kit.mem(from,mkId "mfinally"), [mkFun [], to])
156kit.mapply = (from, fun) ->
157 [from,fun] = kit.spreadApp(from, fun)
158 kit.call(kit.mem(from,mkId("mapply")),[fun])
159
160kit.pure = (v...) ->
161 args = v
162 args = [] if v.length is 1 and not v[0]?
163 kit.call(packId("pure"),args)
164
165kit.exprStmt = mkExprStmt = (expression) ->
166 assert.ok(expression?)
167 return {type:"ExpressionStatement", expression}
168
169kit.assign = mkAssign = (left, right) ->
170 {type:"AssignmentExpression",operator:"=",left,right}
171kit.arr = (els) ->
172 {type:"ArrayExpression", elements: els}
173
174kit.extend = extend = (par, other...) ->
175 for i in other when i?
176 for j, n of i
177 pv = par[j]
178 par[j] = n
179 par
180
181kit.merge = merge = (par, other...) ->
182 for i in other when i?
183 for j, n of i
184 if Array.isArray(n)
185 (par[j] ?= []).push(n...)
186 else if Object(n) is n and not (n instanceof Function)
187 merge(par[j] ?= {},n)
188 else
189 par[j] = n
190 par
191
192kit.exprError = (n, e) ->
193 if e.loc? and e.loc.start?
194 l = e.loc.start.line
195 if l?
196 n = "Line #{l}: #{n}"
197 res = (new Error(n,config.filename,l))
198 res.loc = e.loc
199 res.lineNumber = l
200 res
201
202kit.errorPos = (e, f) ->
203 try
204 return f()
205 catch ex
206 if e.loc? and e.loc.start?
207 l = e.loc.start.line
208 ex.loc = e.loc
209 ex.lineNumber = l
210 ex.message = "Line #{l}: #{ex.message}"
211 throw ex
212
213kit.seqExpr = (expressions...) ->
214 return expressions[0] if expressions.length is 1
215 {type: "SequenceExpression", expressions}
216
217kit.seq = (exprs...) ->
218 return exprs[0] if exprs.length is 1
219 kit.call(packId("seq"), exprs)
220
221kit.getMembersPath = (e) ->
222 res = []
223 walk = (e) ->
224 unless e.type is "MemberExpression"
225 res.unshift e
226 return
227 res.unshift(e.property)
228 walk(e.object)
229 walk(e)
230 res
231
232kit.getMembersPathIds = (e) ->
233 kit.getMembersPath(e).map(kit.getId)
234
235kit.getId = (e) ->
236 return e.name if e? and e.type is "Identifier"
237 return null
238
239kit.coerceThunk = (block) ->
240 kit.call(packId("coerce"),[mkFun([], block)])
241
242kit.coerceVal = (expr) ->
243 kit.call(mkId(config.packageVar),[expr])
244
245getLit = (e) ->
246 return null unless e.type is "Literal"
247 return e.value
248
249kit.toStr = str = (e) ->
250 r = getLit(e)
251 unless r? and r.substr?
252 throw kit.exprError("expected string",e)
253 return r
254
255kit.exprToStr = (e) ->
256 return e.value if e.type is "Literal"
257 throw new Error("cannot convert: " + escodegen.generate(e) + " to string")
258
259kit.shortNodeDescr = (s) ->
260 return "<NULL>" unless s?
261 res = ""
262 res += s.type
263 {loc} = s
264 if loc?
265 {start,end} = loc
266 if start?
267 res += "@#{start.line}:#{start.column}"
268 if end?
269 res += "-#{end.line}:#{end.column}"
270 res
271