linguify 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +45 -0
- data/README.md +167 -0
- data/Rakefile +47 -0
- data/VERSION +1 -0
- data/lib/linguify/linguified.rb +116 -0
- data/lib/linguify/proc.rb +26 -0
- data/lib/linguify/reduction.rb +153 -0
- data/lib/linguify/sexp.rb +60 -0
- data/lib/linguify/string.rb +9 -0
- data/lib/linguify/translators/javascript.rb +513 -0
- data/lib/linguify.rb +34 -0
- data/spec/linguify/linguify_spec.rb +77 -0
- data/tasks/spec.rake +8 -0
- metadata +136 -0
@@ -0,0 +1,513 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# A rewrite of Ruby2Ruby's sexp processor
|
4
|
+
#
|
5
|
+
|
6
|
+
require 'sexp_processor'
|
7
|
+
|
8
|
+
class Ruby2Js < SexpProcessor
|
9
|
+
VERSION = '1.3.1'
|
10
|
+
LINE_LENGTH = 78
|
11
|
+
|
12
|
+
BINARY = [:<=>, :==, :<, :>, :<=, :>=, :-, :+, :*, :/, :%, :<<, :>>, :**]
|
13
|
+
|
14
|
+
##
|
15
|
+
# Nodes that represent assignment and probably need () around them.
|
16
|
+
#
|
17
|
+
# TODO: this should be replaced with full precedence support :/
|
18
|
+
|
19
|
+
ASSIGN_NODES = [
|
20
|
+
:dasgn,
|
21
|
+
:flip2,
|
22
|
+
:flip3,
|
23
|
+
:lasgn,
|
24
|
+
:masgn,
|
25
|
+
:attrasgn,
|
26
|
+
:op_asgn1,
|
27
|
+
:op_asgn2,
|
28
|
+
:op_asgn_and,
|
29
|
+
:op_asgn_or,
|
30
|
+
:return,
|
31
|
+
:if, # HACK
|
32
|
+
]
|
33
|
+
|
34
|
+
def initialize
|
35
|
+
super
|
36
|
+
@indent = " "
|
37
|
+
self.auto_shift_type = true
|
38
|
+
self.strict = true
|
39
|
+
self.expected = String
|
40
|
+
|
41
|
+
@calls = []
|
42
|
+
|
43
|
+
# self.debug[:defn] = /zsuper/
|
44
|
+
end
|
45
|
+
|
46
|
+
def parenthesize exp
|
47
|
+
case self.context[1]
|
48
|
+
when nil, :scope, :if, :iter, :resbody, :when, :while, :until then
|
49
|
+
exp
|
50
|
+
else
|
51
|
+
"(#{exp})"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def indent(s)
|
56
|
+
s.to_s.split(/\n/).map{|line| @indent + line}.join("\n")
|
57
|
+
end
|
58
|
+
|
59
|
+
def cond_loop(exp, name)
|
60
|
+
cond = process(exp.shift)
|
61
|
+
body = process(exp.shift)
|
62
|
+
head_controlled = exp.shift
|
63
|
+
|
64
|
+
body = indent(body).chomp if body
|
65
|
+
|
66
|
+
code = []
|
67
|
+
if head_controlled then
|
68
|
+
if name == 'until'
|
69
|
+
code << "while(!#{cond}){"
|
70
|
+
else
|
71
|
+
code << "#{name}(#{cond}){"
|
72
|
+
end
|
73
|
+
code << body if body
|
74
|
+
code << "}"
|
75
|
+
else
|
76
|
+
code << "begin"
|
77
|
+
code << body if body
|
78
|
+
code << "end #{name} #{cond}"
|
79
|
+
end
|
80
|
+
code.join("\n")
|
81
|
+
end
|
82
|
+
|
83
|
+
def process_and(exp)
|
84
|
+
parenthesize "#{process exp.shift} && #{process exp.shift}"
|
85
|
+
end
|
86
|
+
|
87
|
+
def process_arglist(exp) # custom made node
|
88
|
+
code = []
|
89
|
+
until exp.empty? do
|
90
|
+
code << process(exp.shift)
|
91
|
+
end
|
92
|
+
code.join ', '
|
93
|
+
end
|
94
|
+
|
95
|
+
def process_args(exp)
|
96
|
+
args = []
|
97
|
+
|
98
|
+
until exp.empty? do
|
99
|
+
arg = exp.shift
|
100
|
+
case arg
|
101
|
+
when Symbol then
|
102
|
+
args << arg
|
103
|
+
when Array then
|
104
|
+
case arg.first
|
105
|
+
when :block then
|
106
|
+
asgns = {}
|
107
|
+
arg[1..-1].each do |lasgn|
|
108
|
+
asgns[lasgn[1]] = process(lasgn)
|
109
|
+
end
|
110
|
+
|
111
|
+
args.each_with_index do |name, index|
|
112
|
+
args[index] = asgns[name] if asgns.has_key? name
|
113
|
+
end
|
114
|
+
else
|
115
|
+
raise "unknown arg type #{arg.first.inspect}"
|
116
|
+
end
|
117
|
+
else
|
118
|
+
raise "unknown arg type #{arg.inspect}"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
return "(#{args.join ', '})"
|
123
|
+
end
|
124
|
+
|
125
|
+
def process_array(exp)
|
126
|
+
"[#{process_arglist(exp)}]"
|
127
|
+
end
|
128
|
+
|
129
|
+
def process_attrasgn(exp)
|
130
|
+
receiver = process exp.shift
|
131
|
+
name = exp.shift
|
132
|
+
args = exp.empty? ? nil : exp.shift
|
133
|
+
|
134
|
+
case name
|
135
|
+
when :[]= then
|
136
|
+
rhs = process args.pop
|
137
|
+
"#{receiver}[#{process(args)}] = #{rhs}"
|
138
|
+
else
|
139
|
+
name = name.to_s.sub(/=$/, '')
|
140
|
+
if args && args != s(:arglist) then
|
141
|
+
"#{receiver}.#{name} = #{process(args)}"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def process_block(exp)
|
147
|
+
result = []
|
148
|
+
|
149
|
+
exp << nil if exp.empty?
|
150
|
+
until exp.empty? do
|
151
|
+
code = exp.shift
|
152
|
+
if code.nil? or code.first == :nil then
|
153
|
+
result << "# do nothing\n"
|
154
|
+
else
|
155
|
+
result << process(code)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
result = parenthesize result.join ";\n"
|
160
|
+
result += ";\n" unless result.start_with? "("
|
161
|
+
|
162
|
+
return result
|
163
|
+
end
|
164
|
+
|
165
|
+
def process_break(exp)
|
166
|
+
val = exp.empty? ? nil : process(exp.shift)
|
167
|
+
# HACK "break" + (val ? " #{val}" : "")
|
168
|
+
if val then
|
169
|
+
"break #{val}"
|
170
|
+
else
|
171
|
+
"break"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def process_call(exp)
|
176
|
+
receiver_node_type = exp.first.nil? ? nil : exp.first.first
|
177
|
+
receiver = process exp.shift
|
178
|
+
receiver = "(#{receiver})" if ASSIGN_NODES.include? receiver_node_type
|
179
|
+
|
180
|
+
name = exp.shift
|
181
|
+
args = []
|
182
|
+
raw = []
|
183
|
+
|
184
|
+
# this allows us to do both old and new sexp forms:
|
185
|
+
exp.push(*exp.pop[1..-1]) if exp.size == 1 && exp.first.first == :arglist
|
186
|
+
|
187
|
+
@calls.push name
|
188
|
+
|
189
|
+
in_context :arglist do
|
190
|
+
until exp.empty? do
|
191
|
+
arg_type = exp.first.sexp_type
|
192
|
+
e = exp.shift
|
193
|
+
raw << e.dup
|
194
|
+
arg = process e
|
195
|
+
|
196
|
+
next if arg.empty?
|
197
|
+
|
198
|
+
strip_hash = (arg_type == :hash and
|
199
|
+
not BINARY.include? name and
|
200
|
+
(exp.empty? or exp.first.sexp_type == :splat))
|
201
|
+
wrap_arg = Ruby2Ruby::ASSIGN_NODES.include? arg_type
|
202
|
+
|
203
|
+
arg = arg[2..-3] if strip_hash
|
204
|
+
arg = "(#{arg})" if wrap_arg
|
205
|
+
|
206
|
+
args << arg
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
case name
|
211
|
+
when *BINARY then
|
212
|
+
"(#{receiver} #{name} #{args.join(', ')})"
|
213
|
+
when :[] then
|
214
|
+
receiver ||= "self"
|
215
|
+
if raw.size == 1 && raw.first.sexp_type == :lit && raw.first.to_a[1].kind_of?(Symbol)
|
216
|
+
"#{receiver}.#{args.first[1..-1]}"
|
217
|
+
else
|
218
|
+
"#{receiver}[#{args.join(', ')}]"
|
219
|
+
end
|
220
|
+
when :[]= then
|
221
|
+
receiver ||= "self"
|
222
|
+
rhs = args.pop
|
223
|
+
"#{receiver}[#{args.join(', ')}] = #{rhs}"
|
224
|
+
when :"-@" then
|
225
|
+
"-#{receiver}"
|
226
|
+
when :"+@" then
|
227
|
+
"+#{receiver}"
|
228
|
+
when :new
|
229
|
+
args = nil if args.empty?
|
230
|
+
args = "(#{args.join(',')})" if args
|
231
|
+
receiver = "#{receiver}" if receiver
|
232
|
+
|
233
|
+
"#{name} #{receiver}#{args}"
|
234
|
+
when :lambda
|
235
|
+
receiver = "#{receiver}." if receiver
|
236
|
+
|
237
|
+
"#{receiver}function"
|
238
|
+
when :this # this.something
|
239
|
+
receiver = "#{receiver}." if receiver
|
240
|
+
"#{receiver}#{name}"
|
241
|
+
else
|
242
|
+
args = nil if args.empty?
|
243
|
+
args = "#{args.join(',')}" if args
|
244
|
+
receiver = "#{receiver}." if receiver
|
245
|
+
|
246
|
+
"#{receiver}#{name}(#{args})"
|
247
|
+
end
|
248
|
+
ensure
|
249
|
+
@calls.pop
|
250
|
+
end
|
251
|
+
|
252
|
+
def process_const(exp)
|
253
|
+
exp.shift.to_s
|
254
|
+
end
|
255
|
+
|
256
|
+
def process_defn(exp)
|
257
|
+
type1 = exp[1].first
|
258
|
+
type2 = exp[2].first rescue nil
|
259
|
+
|
260
|
+
if type1 == :args and [:ivar, :attrset].include? type2 then
|
261
|
+
name = exp.shift
|
262
|
+
case type2
|
263
|
+
when :ivar then
|
264
|
+
exp.clear
|
265
|
+
return "attr_reader #{name.inspect}"
|
266
|
+
when :attrset then
|
267
|
+
exp.clear
|
268
|
+
return "attr_writer :#{name.to_s[0..-2]}"
|
269
|
+
else
|
270
|
+
raise "Unknown defn type: #{exp.inspect}"
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
case type1
|
275
|
+
when :scope, :args then
|
276
|
+
name = exp.shift
|
277
|
+
args = process(exp.shift)
|
278
|
+
args = "" if args == "()"
|
279
|
+
body = []
|
280
|
+
until exp.empty? do
|
281
|
+
body << indent(process(exp.shift))
|
282
|
+
end
|
283
|
+
body = body.join("\n")
|
284
|
+
return "#{exp.comments}#{name}#{args}{\n#{body}\n}".gsub(/\n\s*\n+/, "\n")
|
285
|
+
else
|
286
|
+
raise "Unknown defn type: #{type1} for #{exp.inspect}"
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
def process_hash(exp)
|
291
|
+
result = []
|
292
|
+
|
293
|
+
until exp.empty?
|
294
|
+
e = exp.shift
|
295
|
+
if e.sexp_type == :lit
|
296
|
+
lhs = process(e)
|
297
|
+
rhs = exp.shift
|
298
|
+
t = rhs.first
|
299
|
+
rhs = process rhs
|
300
|
+
rhs = "(#{rhs})" unless [:lit, :str, :array, :iter].include? t # TODO: verify better!
|
301
|
+
|
302
|
+
result << "\n#{lhs[1..-1]}: #{rhs}"
|
303
|
+
else
|
304
|
+
lhs = process(e)
|
305
|
+
rhs = exp.shift
|
306
|
+
t = rhs.first
|
307
|
+
rhs = process rhs
|
308
|
+
rhs = "(#{rhs})" unless [:lit, :str].include? t # TODO: verify better!
|
309
|
+
|
310
|
+
result << "\n#{lhs}: #{rhs}"
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
return "{ #{indent(result.join(', '))} }"
|
315
|
+
end
|
316
|
+
|
317
|
+
def process_iasgn(exp)
|
318
|
+
lhs = exp.shift
|
319
|
+
if exp.empty? then # part of an masgn
|
320
|
+
lhs.to_s
|
321
|
+
else
|
322
|
+
if lhs.to_s[0] == '@'
|
323
|
+
"this.#{lhs.to_s[1..-1]} = #{process exp.shift}"
|
324
|
+
else
|
325
|
+
"#{lhs} = #{process exp.shift}"
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
def process_if(exp)
|
331
|
+
expand = Ruby2Ruby::ASSIGN_NODES.include? exp.first.first
|
332
|
+
c = process exp.shift
|
333
|
+
t_type = exp.first.sexp_type if exp.first
|
334
|
+
t = process exp.shift
|
335
|
+
f_type = exp.first.sexp_type if exp.first
|
336
|
+
f = process exp.shift
|
337
|
+
|
338
|
+
c = "(#{c.chomp})" #if c =~ /\n/
|
339
|
+
|
340
|
+
if t then
|
341
|
+
#unless expand then
|
342
|
+
# if f then
|
343
|
+
# r = "#{c} ? (#{t}) : (#{f})"
|
344
|
+
# r = nil if r =~ /return/ # HACK - need contextual awareness or something
|
345
|
+
# else
|
346
|
+
# r = "#{t} if #{c}"
|
347
|
+
# end
|
348
|
+
# return r if r and (@indent+r).size < LINE_LENGTH and r !~ /\n/
|
349
|
+
#end
|
350
|
+
|
351
|
+
r = "if#{c}{\n#{indent(t)}#{[:block, :while, :if].include?(t_type) ? '':';'}\n"
|
352
|
+
r << "}else{\n#{indent(f)}#{[:block, :while, :if].include?(f_type) ? '':';'}\n" if f
|
353
|
+
r << "}"
|
354
|
+
|
355
|
+
r
|
356
|
+
elsif f
|
357
|
+
unless expand then
|
358
|
+
r = "#{f} unless #{c}"
|
359
|
+
return r if (@indent+r).size < LINE_LENGTH and r !~ /\n/
|
360
|
+
end
|
361
|
+
"if(!#{c}){\n#{indent(f)}\n}"
|
362
|
+
else
|
363
|
+
# empty if statement, just do it in case of side effects from condition
|
364
|
+
"if #{c}{\n#{indent '// do nothing'}\n}"
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
def process_iter(exp)
|
369
|
+
iter = process exp.shift
|
370
|
+
args = exp.shift
|
371
|
+
args = (args == 0) ? '' : process(args)
|
372
|
+
body = exp.empty? ? nil : process(exp.shift)
|
373
|
+
|
374
|
+
b, e = #if iter == "END" then
|
375
|
+
[ "{", "}" ]
|
376
|
+
#else
|
377
|
+
# [ "do", "end" ]
|
378
|
+
# end
|
379
|
+
|
380
|
+
iter.sub!(/\(\)$/, '')
|
381
|
+
|
382
|
+
result = []
|
383
|
+
result << "#{iter}(#{args})"
|
384
|
+
result << "#{b}"
|
385
|
+
result << "\n"
|
386
|
+
if body then
|
387
|
+
result << indent(body.strip)
|
388
|
+
result << "\n"
|
389
|
+
end
|
390
|
+
result << e
|
391
|
+
result.join
|
392
|
+
end
|
393
|
+
|
394
|
+
def process_ivar(exp)
|
395
|
+
"this.#{exp.shift.to_s[1..-1]}"
|
396
|
+
end
|
397
|
+
|
398
|
+
def process_lasgn(exp)
|
399
|
+
s = "#{exp.shift}"
|
400
|
+
s += " = #{process exp.shift}" unless exp.empty?
|
401
|
+
s
|
402
|
+
end
|
403
|
+
|
404
|
+
def process_lit(exp)
|
405
|
+
obj = exp.shift
|
406
|
+
case obj
|
407
|
+
when Range then
|
408
|
+
"(#{obj.inspect})"
|
409
|
+
else
|
410
|
+
obj.inspect
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
def process_lvar(exp)
|
415
|
+
exp.shift.to_s
|
416
|
+
end
|
417
|
+
|
418
|
+
def process_masgn(exp)
|
419
|
+
lhs = exp.shift
|
420
|
+
rhs = exp.empty? ? nil : exp.shift
|
421
|
+
|
422
|
+
case lhs.first
|
423
|
+
when :array then
|
424
|
+
lhs.shift
|
425
|
+
lhs = lhs.map do |l|
|
426
|
+
case l.first
|
427
|
+
when :masgn then
|
428
|
+
"(#{process(l)})"
|
429
|
+
else
|
430
|
+
process(l)
|
431
|
+
end
|
432
|
+
end
|
433
|
+
when :lasgn then
|
434
|
+
lhs = [ splat(lhs.last) ]
|
435
|
+
when :splat then
|
436
|
+
lhs = [ :"*" ]
|
437
|
+
else
|
438
|
+
raise "no clue: #{lhs.inspect}"
|
439
|
+
end
|
440
|
+
|
441
|
+
if context[1] == :iter and rhs then
|
442
|
+
lhs << splat(rhs[1])
|
443
|
+
rhs = nil
|
444
|
+
end
|
445
|
+
|
446
|
+
unless rhs.nil? then
|
447
|
+
t = rhs.first
|
448
|
+
rhs = process rhs
|
449
|
+
rhs = rhs[1..-2] if t == :array # FIX: bad? I dunno
|
450
|
+
return "#{lhs.join(", ")} = #{rhs}"
|
451
|
+
else
|
452
|
+
return lhs.join(", ")
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
def process_nil(exp)
|
457
|
+
"null"
|
458
|
+
end
|
459
|
+
|
460
|
+
def process_return(exp)
|
461
|
+
if exp.empty? then
|
462
|
+
return "return"
|
463
|
+
else
|
464
|
+
return "return #{process exp.shift}"
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
def process_scope(exp)
|
469
|
+
exp.empty? ? "" : process(exp.shift)
|
470
|
+
end
|
471
|
+
|
472
|
+
def process_true(exp)
|
473
|
+
"true"
|
474
|
+
end
|
475
|
+
|
476
|
+
def process_until(exp)
|
477
|
+
cond_loop(exp, 'until')
|
478
|
+
end
|
479
|
+
|
480
|
+
def process_while(exp)
|
481
|
+
cond_loop(exp, 'while')
|
482
|
+
end
|
483
|
+
|
484
|
+
end
|
485
|
+
|
486
|
+
module Linguify
|
487
|
+
class Linguified
|
488
|
+
|
489
|
+
def indent
|
490
|
+
@indenture ||= ''
|
491
|
+
@indenture += ' '
|
492
|
+
end
|
493
|
+
def indenture
|
494
|
+
@indenture ||= ''
|
495
|
+
@indenture
|
496
|
+
end
|
497
|
+
def indenture= str
|
498
|
+
@indenture = str
|
499
|
+
end
|
500
|
+
def new_line
|
501
|
+
"\n" + indenture
|
502
|
+
end
|
503
|
+
def dent
|
504
|
+
@indenture ||= ''
|
505
|
+
@indenture = @indenture[2..-1]
|
506
|
+
end
|
507
|
+
|
508
|
+
def to_js sexy = @sexy
|
509
|
+
Ruby2Js.new.process(sexy)
|
510
|
+
end
|
511
|
+
|
512
|
+
end
|
513
|
+
end
|
data/lib/linguify.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'linguify/linguified'
|
4
|
+
require 'linguify/reduction'
|
5
|
+
require 'linguify/sexp'
|
6
|
+
require 'linguify/string'
|
7
|
+
require 'linguify/proc'
|
8
|
+
|
9
|
+
def reduce(regexp,&code)
|
10
|
+
rule = regexp.values[0].kind_of?(Hash) ? {
|
11
|
+
:match => regexp.keys[0],
|
12
|
+
:result => regexp.values[0][:to] || '',
|
13
|
+
:lang => regexp.values[0][:lang] || :ruby,
|
14
|
+
:inline => regexp.values[0][:inline] || false,
|
15
|
+
:proc => code
|
16
|
+
} : {
|
17
|
+
:match => regexp.keys[0],
|
18
|
+
:result => regexp.values[0],
|
19
|
+
:lang => :ruby,
|
20
|
+
:inline => false,
|
21
|
+
:proc => code
|
22
|
+
}
|
23
|
+
Linguify::rules << rule
|
24
|
+
end
|
25
|
+
|
26
|
+
module Linguify
|
27
|
+
|
28
|
+
def self.rules
|
29
|
+
@@rules ||= []
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'linguify'
|
4
|
+
|
5
|
+
describe Linguify::Linguified, "#linguify" do
|
6
|
+
|
7
|
+
it "should reduce multiple rules into ruby code" do
|
8
|
+
|
9
|
+
reduce /all directories/ => 'directories' do
|
10
|
+
Dir.entries('.').select{ |f| f[0] != '.' && File.directory?(f) }
|
11
|
+
end
|
12
|
+
|
13
|
+
reduce /({directories:[^}]*}) recursively/ => 'directories' do |dirs|
|
14
|
+
all_dirs = dirs
|
15
|
+
Find.find(dirs) do |path|
|
16
|
+
if FileTest.directory?(path)
|
17
|
+
if File.basename(path)[0] == '.'
|
18
|
+
Find.prune # Don't look any further into this directory.
|
19
|
+
else
|
20
|
+
all_dirs << path
|
21
|
+
next
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
all_dirs
|
26
|
+
end
|
27
|
+
|
28
|
+
reduce /all files inside ({directories:[^}]*})/ => 'files' do |dirs|
|
29
|
+
dirs.map{ |f| File.new(f, "r") }
|
30
|
+
end
|
31
|
+
|
32
|
+
reduce /view ({files:[^}]*})/ => '' do |files|
|
33
|
+
files.each do |file|
|
34
|
+
pp file
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
"view all files inside all directories recursively".linguify.to_ruby.should == "code = lambda do\n directories_0 = Dir.entries(\".\").select { |f| (not (f[0] == \".\")) and File.directory?(f) }\n directories_1 = (all_dirs = directories_0\n Find.find(directories_0) do |path|\n if FileTest.directory?(path) then\n if (File.basename(path)[0] == \".\") then\n Find.prune\n else\n (all_dirs << path)\n next\n end\n end\n end\n all_dirs)\n files_2 = directories_1.map { |f| File.new(f, \"r\") }\n files_2.each { |file| pp(file) }\nend\n"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should mix javascript and ruby" do
|
42
|
+
reduce /a possible javascript NOSQL query/ => {:to => 'query', :lang => :js} do
|
43
|
+
@db.forEach(lambda{ |record|
|
44
|
+
emit(record);
|
45
|
+
}
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
reduce /execute ({query:[^}]*})/ => '' do |query|
|
50
|
+
db.map query
|
51
|
+
end
|
52
|
+
|
53
|
+
"execute a possible javascript NOSQL query".linguify.to_ruby.should == "code = lambda do\n query = \"function(){\\n this.db.forEach(function(record){\\n emit(record)\\n });\\n}\"\n db.map(query)\nend\n"
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should inline sub-expressions" do
|
57
|
+
reduce /sub expression/ => {:to => 'sub_expression', :lang => :ruby, :inline => true} do
|
58
|
+
pp "this is the sub expression code"
|
59
|
+
end
|
60
|
+
|
61
|
+
reduce /({sub_expression:[^}]*}) of inlined code/ => {:to => 'code', :lang => :ruby, :inline => true} do |sub|
|
62
|
+
something.each do |foobar|
|
63
|
+
pp foobar
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
reduce /execute ({code:[^}]*})/ => '' do |code|
|
68
|
+
pp "hey mum"
|
69
|
+
code
|
70
|
+
code[:sub]
|
71
|
+
pp "you will never know what I just did"
|
72
|
+
end
|
73
|
+
|
74
|
+
"execute sub expression of inlined code".linguify.to_ruby.should == "code = lambda do\n (pp(\"hey mum\")\n (something.each { |foobar| pp(foobar) })\n pp(\"this is the sub expression code\")\n pp(\"you will never know what I just did\"))\nend\n"
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|