rouge-lang 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rouge.rb ADDED
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+
3
+ if RUBY_VERSION < "1.9"
4
+ STDERR.puts "Rouge will probably not run on anything less than Ruby 1.9."
5
+ end
6
+
7
+ module Rouge; end
8
+
9
+ start = Time.now
10
+ Rouge.define_singleton_method :start, lambda {start}
11
+
12
+ class << Rouge
13
+ require 'rouge/version'
14
+ require 'rouge/wrappers'
15
+ require 'rouge/symbol'
16
+ require 'rouge/seq'
17
+ require 'rouge/reader'
18
+ require 'rouge/printer'
19
+ require 'rouge/context'
20
+ require 'rouge/repl'
21
+
22
+ def print(form, out)
23
+ Rouge::Printer.print form, out
24
+ end
25
+
26
+ def [](ns)
27
+ Rouge::Namespace[ns]
28
+ end
29
+
30
+ def boot!
31
+ return if @booted
32
+ @booted = true
33
+
34
+ core = Rouge[:"rouge.core"]
35
+ core.refer Rouge[:"rouge.builtin"]
36
+
37
+ user = Rouge[:user]
38
+ user.refer Rouge[:"rouge.builtin"]
39
+ user.refer Rouge[:"rouge.core"]
40
+ user.refer Rouge[:ruby]
41
+
42
+ Rouge::Context.new(user).readeval(
43
+ File.read(Rouge.relative_to_lib('boot.rg')))
44
+ end
45
+
46
+ def repl(argv)
47
+ boot!
48
+ Rouge::REPL.repl(argv)
49
+ end
50
+
51
+ def relative_to_lib name
52
+ File.join(File.dirname(File.absolute_path(__FILE__)), name)
53
+ end
54
+ end
55
+
56
+ # vim: set sw=2 et cc=80:
data/lib/rouge/atom.rb ADDED
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ class Rouge::Atom
4
+ def initialize(value)
5
+ @value = value
6
+ end
7
+
8
+ def ==(var)
9
+ var.object_id == object_id
10
+ end
11
+
12
+ def deref
13
+ @value
14
+ end
15
+
16
+ def swap! f, *args
17
+ @value = f.call(@value, *args)
18
+ end
19
+
20
+ def reset! v
21
+ @value = v
22
+ end
23
+ end
24
+
25
+ # vim: set sw=2 et cc=80:
@@ -0,0 +1,596 @@
1
+ # encoding: utf-8
2
+
3
+ module Rouge::Builtins
4
+ require 'rouge/compiler'
5
+
6
+ SYMBOLS = {
7
+ :nil => nil,
8
+ :true => true,
9
+ :false => false,
10
+ }
11
+ end
12
+
13
+ class << Rouge::Builtins
14
+ def let(context, bindings, *body)
15
+ context = Rouge::Context.new context
16
+ bindings.to_a.each_slice(2) do |k, v|
17
+ destructure(context, k, v).each do |sk, sv|
18
+ context.set_here sk.name, sv
19
+ end
20
+ end
21
+ self.do(context, *body)
22
+ end
23
+
24
+ def _compile_let(ns, lexicals, bindings, *body)
25
+ lexicals = lexicals.dup
26
+
27
+ bindings = bindings.to_a.each_slice(2).flat_map do |k, v|
28
+ v = Rouge::Compiler.compile(ns, lexicals, v)
29
+ _compile_let_find_lexicals(lexicals, k)
30
+ [k, v]
31
+ end
32
+
33
+ [Rouge::Symbol[:let],
34
+ bindings,
35
+ *Rouge::Compiler.compile(ns, lexicals, body)]
36
+ end
37
+
38
+ def _compile_let_find_lexicals(lexicals, form)
39
+ if form.is_a?(Rouge::Symbol)
40
+ lexicals << form.name
41
+ elsif form.is_a?(Hash) and form.keys == [:keys]
42
+ form.values[0].each do |n|
43
+ lexicals << n.name
44
+ end
45
+ elsif form.is_a?(Hash)
46
+ form.keys.each do |p|
47
+ _compile_let_find_lexicals(lexicals, p)
48
+ end
49
+ elsif form.is_a?(Array)
50
+ form = form.dup
51
+ while form.length > 0
52
+ p = form.shift
53
+
54
+ next if p == :as
55
+ next if p == Rouge::Symbol[:&]
56
+ next if p == Rouge::Symbol[:|]
57
+
58
+ _compile_let_find_lexicals(lexicals, p)
59
+ end
60
+ else
61
+ raise ArgumentError, "unknown LHS of LET expression: #{form.inspect}"
62
+ end
63
+ end
64
+
65
+ def context(context)
66
+ context
67
+ end
68
+
69
+ def quote(context, form)
70
+ form
71
+ end
72
+
73
+ def _compile_quote(ns, lexicals, form)
74
+ [Rouge::Symbol[:quote], form]
75
+ end
76
+
77
+ def fn(context, *args)
78
+ if args[0].is_a? Rouge::Symbol
79
+ name = args.shift.to_sym
80
+ end
81
+
82
+ argv, *body = args
83
+
84
+ if argv[-2] == Rouge::Symbol[:&]
85
+ rest = argv[-1]
86
+ argv = argv[0...-2]
87
+ elsif argv[-4] == Rouge::Symbol[:&] and argv[-2] == Rouge::Symbol[:|]
88
+ rest = argv[-3]
89
+ argv = argv[0...-4] + argv[-2..-1]
90
+ else
91
+ rest = nil
92
+ end
93
+
94
+ if argv[-2] == Rouge::Symbol[:|]
95
+ block = argv[-1]
96
+ argv = argv[0...-2]
97
+ else
98
+ block = nil
99
+ end
100
+
101
+ fn = lambda {|*inner_args, &blockgiven|
102
+ if !rest ? (inner_args.length != argv.length) :
103
+ (inner_args.length < argv.length)
104
+ begin
105
+ raise ArgumentError,
106
+ "wrong number of arguments " \
107
+ "(#{inner_args.length} for #{argv.length})"
108
+ rescue ArgumentError => e
109
+ # orig = e.backtrace.pop
110
+ # e.backtrace.unshift "(rouge):?:FN call (#{name || "<anonymous>"})"
111
+ # e.backtrace.unshift orig
112
+ raise e
113
+ end
114
+ end
115
+
116
+ inner_context = Rouge::Context.new(context)
117
+
118
+ argv.each.with_index do |arg, i|
119
+ inner_context.set_here(arg.name, inner_args[i])
120
+ end
121
+
122
+ if rest
123
+ inner_context.set_here(rest.name,
124
+ Rouge::Seq::Cons[*inner_args[argv.length..-1]])
125
+ end
126
+
127
+ if block
128
+ inner_context.set_here(block.name, blockgiven)
129
+ end
130
+
131
+ begin
132
+ self.do(inner_context, *body)
133
+ rescue => e
134
+ # e.backtrace.unshift "(rouge):?: in #{name || "<anonymous>"}"
135
+ raise e
136
+ end
137
+ }
138
+
139
+ if name
140
+ fn.define_singleton_method(:to_s) { name }
141
+ end
142
+
143
+ fn
144
+ end
145
+
146
+ def _compile_fn(ns, lexicals, *args)
147
+ if args[0].is_a? Rouge::Symbol
148
+ name = args.shift
149
+ end
150
+
151
+ argv, *body = args
152
+
153
+ original_argv = argv
154
+
155
+ if argv[-2] == Rouge::Symbol[:&]
156
+ rest = argv[-1]
157
+ argv = argv[0...-2]
158
+ elsif argv[-4] == Rouge::Symbol[:&] and argv[-2] == Rouge::Symbol[:|]
159
+ rest = argv[-3]
160
+ argv = argv[0...-4] + argv[-2..-1]
161
+ else
162
+ rest = nil
163
+ end
164
+
165
+ if argv[-2] == Rouge::Symbol[:|]
166
+ block = argv[-1]
167
+ argv = argv[0...-2]
168
+ else
169
+ block = nil
170
+ end
171
+
172
+ lexicals = lexicals.dup
173
+ argv.each do |arg|
174
+ lexicals << arg.name
175
+ end
176
+ lexicals << rest.name if rest
177
+ lexicals << block.name if block
178
+
179
+ [Rouge::Symbol[:fn],
180
+ *(name ? [name] : []),
181
+ original_argv,
182
+ *Rouge::Compiler.compile(ns, lexicals, body)]
183
+ end
184
+
185
+ def def(context, name, *form)
186
+ if name.ns != nil
187
+ raise ArgumentError, "cannot def qualified var"
188
+ end
189
+
190
+ case form.length
191
+ when 0
192
+ context.ns.intern name.name
193
+ when 1
194
+ context.ns.set_here name.name, context.eval(form[0])
195
+ else
196
+ raise ArgumentError, "def called with too many forms #{form.inspect}"
197
+ end
198
+ end
199
+
200
+ def _compile_def(ns, lexicals, name, *form)
201
+ if name.ns != nil
202
+ raise ArgumentError, "cannot def qualified var"
203
+ end
204
+
205
+ lexicals = lexicals.dup
206
+ lexicals << name.name
207
+
208
+ [Rouge::Symbol[:def],
209
+ name,
210
+ *Rouge::Compiler.compile(ns, lexicals, form)]
211
+ end
212
+
213
+ def if(context, test, if_true, if_false=nil)
214
+ # Note that we rely on Ruby's sense of truthiness. (only false and nil are
215
+ # falsey)
216
+ if context.eval(test)
217
+ context.eval if_true
218
+ else
219
+ context.eval if_false
220
+ end
221
+ end
222
+
223
+ def do(context, *forms)
224
+ r = nil
225
+
226
+ while forms.length > 0
227
+ begin
228
+ form = Rouge::Compiler.compile(
229
+ context.ns,
230
+ Set[*context.lexical_keys],
231
+ forms.shift)
232
+
233
+ r = context.eval(form)
234
+ rescue Rouge::Context::ChangeContextException => cce
235
+ context = cce.context
236
+ end
237
+ end
238
+
239
+ r
240
+ end
241
+
242
+ def _compile_do(ns, lexicals, *forms)
243
+ [Rouge::Symbol[:do], *forms]
244
+ end
245
+
246
+ def ns(context, name, *args)
247
+ ns = Rouge[name.name]
248
+ ns.refer Rouge[:"rouge.builtin"]
249
+
250
+ args.each do |arg|
251
+ kind, *params = arg.to_a
252
+
253
+ case kind
254
+ when :use
255
+ params.each do |use|
256
+ ns.refer Rouge[use.name]
257
+ end
258
+ when :require
259
+ params.each do |param|
260
+ if param.is_a? Rouge::Symbol
261
+ Kernel.require param.name.to_s
262
+ elsif param.is_a? Array and
263
+ param.length == 3 and
264
+ param[0].is_a? Rouge::Symbol and
265
+ param[1] == :as and
266
+ param[2].is_a? Rouge::Symbol
267
+ unless Rouge::Namespace.exists? param[0].name
268
+ context.readeval(File.read("#{param[0].name}.rg"))
269
+ end
270
+ Rouge::Namespace[param[2].name] = Rouge[param[0].name]
271
+ end
272
+ end
273
+ else
274
+ raise "TODO bad arg in ns: #{kind}"
275
+ end
276
+ end
277
+
278
+ context = Rouge::Context.new ns
279
+ raise Rouge::Context::ChangeContextException, context
280
+ end
281
+
282
+ def _compile_ns(ns, lexicals, name, *args)
283
+ [Rouge::Symbol[:ns], name, *args]
284
+ end
285
+
286
+ def defmacro(context, name, *parts)
287
+ if name.ns
288
+ raise ArgumentError, "cannot defmacro fully qualified var"
289
+ end
290
+
291
+ if parts[0].is_a? Array
292
+ args, *body = parts
293
+ macro = Rouge::Macro[
294
+ context.eval(Rouge::Seq::Cons[Rouge::Symbol[:fn], args, *body])]
295
+ elsif parts.all? {|part| part.is_a? Rouge::Seq::Cons}
296
+ arities = {}
297
+
298
+ parts.each do |cons|
299
+ args, *body = cons.to_a
300
+
301
+ if !args.is_a? Array
302
+ raise ArgumentError,
303
+ "bad multi-form defmacro component #{args.inspect}"
304
+ end
305
+
306
+ if args.index(Rouge::Symbol[:&])
307
+ arity = -1
308
+ else
309
+ arity = args.length
310
+ end
311
+
312
+ if arities[arity]
313
+ raise ArgumentError, "seen same arity twice"
314
+ end
315
+
316
+ arities[arity] =
317
+ context.eval(Rouge::Seq::Cons[Rouge::Symbol[:fn], args, *body])
318
+ end
319
+
320
+ macro = Rouge::Macro[
321
+ lambda {|*inner_args, &blockgiven|
322
+ if arities[inner_args.length]
323
+ arities[inner_args.length].call(*inner_args, &blockgiven)
324
+ elsif arities[-1]
325
+ arities[-1].call(*inner_args, &blockgiven)
326
+ else
327
+ raise ArgumentError, "no matching arity in macro"
328
+ end
329
+ }]
330
+ else
331
+ raise ArgumentError, "neither single-form defmacro nor multi-form"
332
+ end
333
+
334
+ macro.define_singleton_method(:to_s) { :"#{context.ns.name}/#{name.name}" }
335
+
336
+ context.ns.set_here name.name, macro
337
+ end
338
+
339
+ def _compile_defmacro(ns, lexicals, name, *parts)
340
+ if name.ns
341
+ raise ArgumentError, "cannot defmacro fully qualified var"
342
+ end
343
+
344
+ if parts[0].is_a? Array
345
+ args, *body = parts
346
+ [Rouge::Symbol[:defmacro],
347
+ name,
348
+ *_compile_fn(ns, lexicals, args, *body)[1..-1]]
349
+ elsif parts.all? {|part| part.is_a? Rouge::Seq::Cons}
350
+ [Rouge::Symbol[:defmacro],
351
+ name,
352
+ *parts.map do |cons|
353
+ args, *body = cons.to_a
354
+
355
+ if !args.is_a? Array
356
+ raise ArgumentError,
357
+ "bad multi-form defmacro component #{args.inspect}"
358
+ end
359
+
360
+ Rouge::Seq::Cons[*_compile_fn(ns, lexicals, args, *body)[1..-1]]
361
+ end]
362
+ else
363
+ raise ArgumentError, "neither single-form defmacro nor multi-form"
364
+ end
365
+ end
366
+
367
+ def apply(context, fun, *args)
368
+ args =
369
+ args[0..-2].map {|f| context.eval f} +
370
+ context.eval(args[-1]).to_a
371
+ # This is a terrible hack.
372
+ context.eval(Rouge::Seq::Cons[
373
+ fun,
374
+ *args.map {|a| Rouge::Seq::Cons[Rouge::Symbol[:quote], a]}])
375
+ end
376
+
377
+ def var(context, f)
378
+ # HACK: just so it'll be found when fully qualified.
379
+ f
380
+ end
381
+
382
+ def _compile_var(ns, lexicals, symbol)
383
+ if symbol.ns
384
+ [Rouge::Symbol[:quote], Rouge[symbol.ns][symbol.name]]
385
+ else
386
+ [Rouge::Symbol[:quote], ns[symbol.name]]
387
+ end
388
+ end
389
+
390
+ def throw(context, throwable)
391
+ exception = context.eval(throwable)
392
+ begin
393
+ raise exception
394
+ rescue Exception => e
395
+ # TODO
396
+ #e.backtrace.unshift "(rouge):?:throw"
397
+ raise e
398
+ end
399
+ end
400
+
401
+ def try(context, *body)
402
+ return unless body.length > 0
403
+
404
+ form = body[-1]
405
+ if form.is_a?(Rouge::Seq::Cons) and
406
+ form[0].is_a? Rouge::Symbol and
407
+ form[0].name == :finally
408
+ finally = form[1..-1].freeze
409
+ body.pop
410
+ end
411
+
412
+ catches = {}
413
+ while body.length > 0
414
+ form = body[-1]
415
+ if !form.is_a?(Rouge::Seq::Cons) or
416
+ !form[0].is_a? Rouge::Symbol or
417
+ form[0].name != :catch
418
+ break
419
+ end
420
+
421
+ body.pop
422
+ catches[context.eval(form[1])] =
423
+ {:bind => form[2],
424
+ :body => form[3..-1].freeze}
425
+ end
426
+
427
+ r =
428
+ begin
429
+ self.do(context, *body)
430
+ rescue Exception => e
431
+ catches.each do |klass, caught|
432
+ if klass === e
433
+ subcontext = Rouge::Context.new context
434
+ subcontext.set_here caught[:bind].name, e
435
+ r = self.do(subcontext, *caught[:body])
436
+ self.do(context, *finally) if finally
437
+ return r
438
+ end
439
+ end
440
+ self.do(context, *finally) if finally
441
+ raise e
442
+ end
443
+
444
+ self.do(context, *finally) if finally
445
+ r
446
+ end
447
+
448
+ def _compile_try(ns, lexicals, *body)
449
+ return [Rouge::Symbol[:try]] unless body.length > 0
450
+
451
+ form = body[-1]
452
+ if form.is_a?(Rouge::Seq::Cons) and
453
+ form[0].is_a? Rouge::Symbol and
454
+ form[0].name == :finally
455
+ finally = form[1..-1].freeze
456
+ body.pop
457
+ end
458
+
459
+ catches = []
460
+ while body.length > 0
461
+ form = body[-1]
462
+ if !form.is_a?(Rouge::Seq::Cons) or
463
+ !form[0].is_a? Rouge::Symbol or
464
+ form[0].name != :catch
465
+ break
466
+ end
467
+
468
+ body.pop
469
+ catches <<
470
+ {:class => form[1],
471
+ :bind => form[2],
472
+ :body => form[3..-1].freeze}
473
+ end
474
+
475
+ form =
476
+ [Rouge::Symbol[:try],
477
+ *Rouge::Compiler.compile(ns, lexicals, body),
478
+ *catches.reverse.map {|c|
479
+ if !c[:bind].is_a?(Rouge::Symbol) or c[:bind].ns
480
+ raise ArgumentError, "bad catch binding #{c[:bind]}"
481
+ end
482
+
483
+ bind_lexicals = lexicals.dup << c[:bind].name
484
+ Rouge::Seq::Cons[Rouge::Symbol[:catch],
485
+ Rouge::Compiler.compile(ns, lexicals, c[:class]),
486
+ c[:bind],
487
+ *c[:body].map {|f|
488
+ Rouge::Compiler.compile(ns, bind_lexicals, f)
489
+ }]
490
+ },
491
+ *(finally ? [Rouge::Seq::Cons[Rouge::Symbol[:finally],
492
+ *finally.map {|f|
493
+ Rouge::Compiler.compile(ns, lexicals, f)
494
+ }]] : [])]
495
+ end
496
+
497
+ def destructure(context, parameters, values, evalled=false, r={})
498
+ # TODO: can probably move this elsewhere as a regular function.
499
+
500
+ if parameters.is_a?(Rouge::Symbol)
501
+ values = context.eval(values) if !evalled
502
+ r[parameters] = values
503
+ return r
504
+ end
505
+
506
+ if parameters.is_a?(Hash) and parameters.keys == [:keys]
507
+ keys = parameters.values[0]
508
+ context.eval(values).select do |k,v|
509
+ keys.include?(Rouge::Symbol[k])
510
+ end.each {|k,v| r[Rouge::Symbol[k]] = v}
511
+ return r
512
+ end
513
+
514
+ if parameters.is_a?(Hash)
515
+ values = context.eval(values) if !evalled
516
+ parameters.each do |local, foreign|
517
+ destructure(context, local, values[foreign], true, r)
518
+ end
519
+ return r
520
+ end
521
+
522
+ if !parameters.is_a?(Array) and !evalled
523
+ raise ArgumentError, "unknown destructure parameter list"
524
+ end
525
+
526
+ if !evalled and values.is_a? Array
527
+ if values[-2] == Rouge::Symbol[:|]
528
+ block = context.eval(values[-1])
529
+ block_supplied = true
530
+
531
+ values = values[0...-2]
532
+ end
533
+
534
+ if values[-2] == Rouge::Symbol[:&]
535
+ values =
536
+ values[0...-2].map {|v| context.eval(v)} +
537
+ context.eval(values[-1]).to_a
538
+ else
539
+ values = values.map {|v| context.eval(v)}
540
+ end
541
+ else
542
+ values = context.eval(values)
543
+ end
544
+
545
+ values = Rouge::Seq.seq(values)
546
+ original_values = values
547
+
548
+ parameters = parameters.dup
549
+ while parameters.length > 0
550
+ p = parameters.shift
551
+
552
+ if p == Rouge::Symbol[:&]
553
+ r[parameters.shift] = values
554
+ values = Rouge::Seq::Empty
555
+ next
556
+ end
557
+
558
+ if p == Rouge::Symbol[:|]
559
+ if not block_supplied
560
+ raise ArgumentError, "no block supplied"
561
+ end
562
+
563
+ r[parameters.shift] = block
564
+ next
565
+ end
566
+
567
+ if p == :as
568
+ r[parameters.shift] = Rouge::Seq.seq(original_values)
569
+ values = Rouge::Seq::Empty
570
+ next
571
+ end
572
+
573
+ if p.is_a? Array
574
+ destructure(context, p, Rouge::Seq.seq(values.first), true, r)
575
+ else
576
+ if p.ns
577
+ raise Rouge::Context::BadBindingError,
578
+ "cannot let qualified name in DESTRUCTURE"
579
+ end
580
+ r[p] = values ? values.first : nil
581
+ end
582
+
583
+ values = values ? values.next : nil
584
+ end
585
+
586
+ r
587
+ end
588
+
589
+ def _compile_destructure(ns, lexicals, parameters, values)
590
+ [Rouge::Symbol[:destructure],
591
+ parameters,
592
+ Rouge::Compiler.compile(ns, lexicals, values)]
593
+ end
594
+ end
595
+
596
+ # vim: set sw=2 et cc=80: