1 | kit = module.exports = {}
|
2 | config = require "./config"
|
3 | escodegen = require "escodegen"
|
4 | assert = require "assert"
|
5 | esutils = require "esutils"
|
6 | esast = esutils.ast
|
7 |
|
8 | kit.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 |
|
15 | kit.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 |
|
33 | kit.blockStmts = (stmt) ->
|
34 | return stmt.body if stmt.type is "BlockStatement"
|
35 | [stmt]
|
36 |
|
37 | kit.ret = mkReturn = (argument) ->
|
38 | {type:"ReturnStatement",argument}
|
39 |
|
40 | kit.call = (callee,args) ->
|
41 | callee = kit.id(callee) if callee.substr?
|
42 | {type:"CallExpression",callee,arguments:args}
|
43 |
|
44 | kit.id = mkId = (name) -> {type:"Identifier",name}
|
45 |
|
46 | kit.varDecl = (n, v) ->
|
47 | {
|
48 | type:"VariableDeclaration", kind: "var",
|
49 | declarations:[{
|
50 | type: "VariableDeclarator"
|
51 | id: n
|
52 | init: v
|
53 | }]}
|
54 |
|
55 | kit.packId = packId = (id) ->
|
56 | p = config.packageVar
|
57 | return id unless p?
|
58 | kit.mem (mkId p), (mkId id)
|
59 |
|
60 | kit.spread = (fun) ->
|
61 | return kit.call(kit.packId("spread"),[fun])
|
62 |
|
63 | kit.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 |
|
72 | kit.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 |
|
78 | kit.halt = mkHalt = -> kit.call(kit.id("halt"),[])
|
79 |
|
80 | kit.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
|
90 | noThisNeeded ?= {}
|
91 |
|
92 |
|
93 | kit.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 |
|
111 | matchSingleCallBlock = (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 |
|
120 | kit.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 |
|
126 | kit.lit = mkLit = (v) -> {type:"Literal",value: v}
|
127 |
|
128 | kit.coerce = (v) -> kit.call(packId("coerce"),[mkFun([],v)])
|
129 |
|
130 | kit.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 |
|
138 | kit.not = (argument) ->
|
139 | {type:"UnaryExpression",prefix:true,operator:"!",argument}
|
140 | kit.eq = (left, right) ->
|
141 | {type:"BinaryExpression",operator:"===",left,right}
|
142 |
|
143 | kit.arrM = (args) -> kit.call(kit.packId("arr"), [kit.arr(args)])
|
144 |
|
145 | kit.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])
|
150 | kit.catch = (from, arg, to) ->
|
151 | args = []
|
152 | args.push arg if arg?
|
153 | return kit.call(kit.mem(from,mkId "mhandle"),[mkFun(args, to)])
|
154 | kit.finally = (from, to) ->
|
155 | return kit.call(kit.mem(from,mkId "mfinally"), [mkFun [], to])
|
156 | kit.mapply = (from, fun) ->
|
157 | [from,fun] = kit.spreadApp(from, fun)
|
158 | kit.call(kit.mem(from,mkId("mapply")),[fun])
|
159 |
|
160 | kit.pure = (v...) ->
|
161 | args = v
|
162 | args = [] if v.length is 1 and not v[0]?
|
163 | kit.call(packId("pure"),args)
|
164 |
|
165 | kit.exprStmt = mkExprStmt = (expression) ->
|
166 | assert.ok(expression?)
|
167 | return {type:"ExpressionStatement", expression}
|
168 |
|
169 | kit.assign = mkAssign = (left, right) ->
|
170 | {type:"AssignmentExpression",operator:"=",left,right}
|
171 | kit.arr = (els) ->
|
172 | {type:"ArrayExpression", elements: els}
|
173 |
|
174 | kit.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 |
|
181 | kit.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 |
|
192 | kit.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 |
|
202 | kit.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 |
|
213 | kit.seqExpr = (expressions...) ->
|
214 | return expressions[0] if expressions.length is 1
|
215 | {type: "SequenceExpression", expressions}
|
216 |
|
217 | kit.seq = (exprs...) ->
|
218 | return exprs[0] if exprs.length is 1
|
219 | kit.call(packId("seq"), exprs)
|
220 |
|
221 | kit.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 |
|
232 | kit.getMembersPathIds = (e) ->
|
233 | kit.getMembersPath(e).map(kit.getId)
|
234 |
|
235 | kit.getId = (e) ->
|
236 | return e.name if e? and e.type is "Identifier"
|
237 | return null
|
238 |
|
239 | kit.coerceThunk = (block) ->
|
240 | kit.call(packId("coerce"),[mkFun([], block)])
|
241 |
|
242 | kit.coerceVal = (expr) ->
|
243 | kit.call(mkId(config.packageVar),[expr])
|
244 |
|
245 | getLit = (e) ->
|
246 | return null unless e.type is "Literal"
|
247 | return e.value
|
248 |
|
249 | kit.toStr = str = (e) ->
|
250 | r = getLit(e)
|
251 | unless r? and r.substr?
|
252 | throw kit.exprError("expected string",e)
|
253 | return r
|
254 |
|
255 | kit.exprToStr = (e) ->
|
256 | return e.value if e.type is "Literal"
|
257 | throw new Error("cannot convert: " + escodegen.generate(e) + " to string")
|
258 |
|
259 | kit.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 |
|