rouge-lang 0.0.1

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/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: