atomy 0.1.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/COPYING +30 -0
- data/README.md +1 -0
- data/bin/atomy +134 -0
- data/kernel/block.ay +30 -0
- data/kernel/boot.ay +10 -0
- data/kernel/comparison.ay +61 -0
- data/kernel/concurrency.ay +84 -0
- data/kernel/condition.ay +277 -0
- data/kernel/control-flow.ay +222 -0
- data/kernel/cosmetics.ay +3 -0
- data/kernel/data-delta.ay +105 -0
- data/kernel/data.ay +56 -0
- data/kernel/define.ay +93 -0
- data/kernel/doc.ay +453 -0
- data/kernel/documentation.ay +135 -0
- data/kernel/dynamic.ay +42 -0
- data/kernel/errors.ay +6 -0
- data/kernel/format.ay +13 -0
- data/kernel/format/data.ay +89 -0
- data/kernel/format/formatter.ay +345 -0
- data/kernel/format/parser.ay +13 -0
- data/kernel/hashes.ay +39 -0
- data/kernel/io.ay +244 -0
- data/kernel/namespaces.ay +63 -0
- data/kernel/node.ay +48 -0
- data/kernel/operators.ay +28 -0
- data/kernel/particles.ay +53 -0
- data/kernel/patterns.ay +256 -0
- data/kernel/precision.ay +148 -0
- data/kernel/pretty.ay +283 -0
- data/kernel/repl.ay +140 -0
- data/kernel/therie.ay +204 -0
- data/lib/ast/binary_send.rb +44 -0
- data/lib/ast/block.rb +268 -0
- data/lib/ast/constant.rb +88 -0
- data/lib/ast/internal/assign.rb +19 -0
- data/lib/ast/internal/block_pass.rb +21 -0
- data/lib/ast/internal/catch.rb +247 -0
- data/lib/ast/internal/class.rb +30 -0
- data/lib/ast/internal/class_variable.rb +23 -0
- data/lib/ast/internal/define.rb +174 -0
- data/lib/ast/internal/ensure.rb +135 -0
- data/lib/ast/internal/file.rb +14 -0
- data/lib/ast/internal/global_variable.rb +20 -0
- data/lib/ast/internal/if_then_else.rb +24 -0
- data/lib/ast/internal/instance_variable.rb +17 -0
- data/lib/ast/internal/let_macro.rb +35 -0
- data/lib/ast/internal/macro_quote.rb +23 -0
- data/lib/ast/internal/match.rb +53 -0
- data/lib/ast/internal/module.rb +30 -0
- data/lib/ast/internal/pattern.rb +17 -0
- data/lib/ast/internal/return.rb +29 -0
- data/lib/ast/internal/set.rb +19 -0
- data/lib/ast/internal/singleton_class.rb +18 -0
- data/lib/ast/internal/splat.rb +14 -0
- data/lib/ast/internal/when.rb +24 -0
- data/lib/ast/list.rb +25 -0
- data/lib/ast/macro.rb +37 -0
- data/lib/ast/node.rb +599 -0
- data/lib/ast/operator.rb +21 -0
- data/lib/ast/particle.rb +13 -0
- data/lib/ast/primitive.rb +20 -0
- data/lib/ast/quasi_quote.rb +20 -0
- data/lib/ast/quote.rb +13 -0
- data/lib/ast/send.rb +104 -0
- data/lib/ast/splice.rb +32 -0
- data/lib/ast/string.rb +23 -0
- data/lib/ast/unary.rb +44 -0
- data/lib/ast/unquote.rb +45 -0
- data/lib/ast/variable.rb +64 -0
- data/lib/atomy.kpeg.rb +3995 -0
- data/lib/code_loader.rb +137 -0
- data/lib/compiler/compiler.rb +155 -0
- data/lib/compiler/stages.rb +81 -0
- data/lib/formatter.kpeg.rb +1394 -0
- data/lib/macros.rb +317 -0
- data/lib/method.rb +261 -0
- data/lib/namespace.rb +236 -0
- data/lib/parser.rb +28 -0
- data/lib/patterns.rb +276 -0
- data/lib/patterns/any.rb +21 -0
- data/lib/patterns/attribute.rb +59 -0
- data/lib/patterns/block_pass.rb +54 -0
- data/lib/patterns/constant.rb +33 -0
- data/lib/patterns/default.rb +44 -0
- data/lib/patterns/head_tail.rb +63 -0
- data/lib/patterns/list.rb +77 -0
- data/lib/patterns/match.rb +45 -0
- data/lib/patterns/named.rb +55 -0
- data/lib/patterns/named_class.rb +46 -0
- data/lib/patterns/named_global.rb +46 -0
- data/lib/patterns/named_instance.rb +46 -0
- data/lib/patterns/particle.rb +29 -0
- data/lib/patterns/quasi_quote.rb +184 -0
- data/lib/patterns/quote.rb +33 -0
- data/lib/patterns/singleton_class.rb +31 -0
- data/lib/patterns/splat.rb +57 -0
- data/lib/util.rb +37 -0
- metadata +164 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
module Atomy
|
2
|
+
module AST
|
3
|
+
class When < Node
|
4
|
+
children :condition, :then
|
5
|
+
generate
|
6
|
+
|
7
|
+
def bytecode(g)
|
8
|
+
done = g.new_label
|
9
|
+
nope = g.new_label
|
10
|
+
|
11
|
+
@condition.compile(g)
|
12
|
+
g.gif nope
|
13
|
+
|
14
|
+
@then.compile(g)
|
15
|
+
g.goto done
|
16
|
+
|
17
|
+
nope.set!
|
18
|
+
g.push_nil
|
19
|
+
|
20
|
+
done.set!
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/ast/list.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Atomy
|
2
|
+
module AST
|
3
|
+
class List < Node
|
4
|
+
children [:elements]
|
5
|
+
generate
|
6
|
+
|
7
|
+
def as_message(send)
|
8
|
+
send.dup.tap do |s|
|
9
|
+
s.arguments = @elements
|
10
|
+
s.method_name = "[]"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def bytecode(g)
|
15
|
+
pos(g)
|
16
|
+
|
17
|
+
@elements.each do |e|
|
18
|
+
e.compile(g)
|
19
|
+
end
|
20
|
+
|
21
|
+
g.make_array @elements.size
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/ast/macro.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module Atomy
|
2
|
+
module AST
|
3
|
+
class Macro < Node
|
4
|
+
children :pattern, :body
|
5
|
+
generate
|
6
|
+
|
7
|
+
def bytecode(g)
|
8
|
+
# register macro during compilation too.
|
9
|
+
@pattern.register_macro @body
|
10
|
+
|
11
|
+
done = g.new_label
|
12
|
+
skip = g.new_label
|
13
|
+
|
14
|
+
g.push_cpath_top
|
15
|
+
g.find_const :Atomy
|
16
|
+
g.find_const :CodeLoader
|
17
|
+
g.send :compiled?, 0
|
18
|
+
g.git skip
|
19
|
+
|
20
|
+
load_bytecode(g)
|
21
|
+
g.goto done
|
22
|
+
|
23
|
+
skip.set!
|
24
|
+
g.push_nil
|
25
|
+
|
26
|
+
done.set!
|
27
|
+
end
|
28
|
+
|
29
|
+
def load_bytecode(g)
|
30
|
+
pos(g)
|
31
|
+
@pattern.construct(g)
|
32
|
+
@body.construct(g)
|
33
|
+
g.send :register_macro, 1
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/ast/node.rb
ADDED
@@ -0,0 +1,599 @@
|
|
1
|
+
module Atomy
|
2
|
+
def self.unquote_splice(n)
|
3
|
+
n.collect do |x|
|
4
|
+
Atomy::AST::Quote.new(x.line, x)
|
5
|
+
end.to_node
|
6
|
+
end
|
7
|
+
|
8
|
+
module AST
|
9
|
+
module SentientNode
|
10
|
+
# hash from attribute to the type of child node it is
|
11
|
+
# :normal = normal, required subnode
|
12
|
+
# :many = an array of subnodes
|
13
|
+
# :optional = optional (might be nil)
|
14
|
+
def reset_children
|
15
|
+
@@children = {
|
16
|
+
:required => [],
|
17
|
+
:many => [],
|
18
|
+
:optional => []
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def reset_attributes
|
23
|
+
@@attributes = {
|
24
|
+
:required => [],
|
25
|
+
:many => [],
|
26
|
+
:optional => []
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def reset_slots
|
31
|
+
@@slots = {
|
32
|
+
:required => [],
|
33
|
+
:many => [],
|
34
|
+
:optional => []
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def inherited(sub)
|
39
|
+
sub.reset_children
|
40
|
+
sub.reset_attributes
|
41
|
+
sub.reset_slots
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.extended(sub)
|
45
|
+
sub.reset_children
|
46
|
+
sub.reset_attributes
|
47
|
+
sub.reset_slots
|
48
|
+
end
|
49
|
+
|
50
|
+
def spec(into, specs)
|
51
|
+
specs.each do |s|
|
52
|
+
if s.kind_of?(Array)
|
53
|
+
if s.size == 2
|
54
|
+
into[:optional] << s
|
55
|
+
else
|
56
|
+
into[:many] << s[0]
|
57
|
+
end
|
58
|
+
elsif s.to_s[-1] == ??
|
59
|
+
into[:optional] << [s.to_s[0..-2].to_sym, "nil"]
|
60
|
+
else
|
61
|
+
into[:required] << s
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def attributes(*specs)
|
67
|
+
spec(@@attributes, specs)
|
68
|
+
end
|
69
|
+
|
70
|
+
def slots(*specs)
|
71
|
+
spec(@@slots, specs)
|
72
|
+
end
|
73
|
+
|
74
|
+
def children(*specs)
|
75
|
+
spec(@@children, specs)
|
76
|
+
end
|
77
|
+
|
78
|
+
def many_construct(n)
|
79
|
+
x = <<END
|
80
|
+
spliced = false
|
81
|
+
size = 0
|
82
|
+
@#{n}.each do |e|
|
83
|
+
if e.kind_of?(::Atomy::AST::Splice) && d == 1
|
84
|
+
g.make_array size if size > 0
|
85
|
+
e.construct(g, d)
|
86
|
+
g.send :+, 1 if size > 0 || spliced
|
87
|
+
spliced = true
|
88
|
+
size = 0
|
89
|
+
else
|
90
|
+
e.construct(g, d)
|
91
|
+
size += 1
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
g.make_array size
|
96
|
+
|
97
|
+
g.send :+, 1 if spliced
|
98
|
+
END
|
99
|
+
x
|
100
|
+
end
|
101
|
+
|
102
|
+
def generate
|
103
|
+
all = []
|
104
|
+
args = ""
|
105
|
+
(@@children[:required] + @@children[:many] +
|
106
|
+
@@attributes[:required] + @@attributes[:many] +
|
107
|
+
@@slots[:required] + @@slots[:many]).each do |x|
|
108
|
+
all << x.to_s
|
109
|
+
args << ", #{x}_"
|
110
|
+
end
|
111
|
+
|
112
|
+
(@@children[:optional] + @@attributes[:optional]).each do |x, d|
|
113
|
+
all << x.to_s
|
114
|
+
args << ", #{x}_ = #{d}"
|
115
|
+
end
|
116
|
+
|
117
|
+
non_slots = all.dup
|
118
|
+
@@slots[:optional].each do |x, d|
|
119
|
+
all << x.to_s
|
120
|
+
args << ", #{x}_ = #{d}"
|
121
|
+
end
|
122
|
+
|
123
|
+
class_eval <<EOF
|
124
|
+
attr_accessor :line#{all.collect { |a| ", :#{a}" }.join}
|
125
|
+
EOF
|
126
|
+
|
127
|
+
class_eval <<EOF
|
128
|
+
def initialize(line#{args})
|
129
|
+
@line = line
|
130
|
+
#{all.collect { |a| "@#{a} = #{a}_" }.join("; ")}
|
131
|
+
end
|
132
|
+
EOF
|
133
|
+
|
134
|
+
class_eval <<EOF
|
135
|
+
def construct(g, d = nil)
|
136
|
+
get(g)
|
137
|
+
g.push_int(@line)
|
138
|
+
|
139
|
+
#{@@children[:required].collect { |n|
|
140
|
+
"@#{n}.construct(g, d)"
|
141
|
+
}.join("; ")}
|
142
|
+
|
143
|
+
#{@@children[:many].collect { |n|
|
144
|
+
many_construct(n)
|
145
|
+
}.join("; ")}
|
146
|
+
|
147
|
+
#{@@attributes[:required].collect { |a|
|
148
|
+
"g.push_literal(@#{a})"
|
149
|
+
}.join("; ")}
|
150
|
+
|
151
|
+
#{@@attributes[:many].collect { |a|
|
152
|
+
"@#{a}.each { |n| g.push_literal n }; g.make_array(@#{a}.size)"
|
153
|
+
}.join("; ")}
|
154
|
+
|
155
|
+
#{@@slots[:required].collect { |a|
|
156
|
+
"g.push_literal(@#{a})"
|
157
|
+
}.join("; ")}
|
158
|
+
|
159
|
+
#{@@slots[:many].collect { |a|
|
160
|
+
"@#{a}.each { |n| g.push_literal n }; g.make_array(@#{a}.size)"
|
161
|
+
}.join("; ")}
|
162
|
+
|
163
|
+
#{@@children[:optional].collect { |n, _|
|
164
|
+
"if @#{n}; @#{n}.construct(g, d); else; g.push_nil; end"
|
165
|
+
}.join("; ")}
|
166
|
+
|
167
|
+
#{@@attributes[:optional].collect { |a, _|
|
168
|
+
"g.push_literal(@#{a})"
|
169
|
+
}.join("; ")}
|
170
|
+
|
171
|
+
#{@@slots[:optional].collect { |a, _|
|
172
|
+
"g.push_literal(@#{a})"
|
173
|
+
}.join("; ")}
|
174
|
+
|
175
|
+
g.send :new, #{all.size + 1}
|
176
|
+
end
|
177
|
+
EOF
|
178
|
+
|
179
|
+
class_eval <<EOF
|
180
|
+
def ==(b)
|
181
|
+
b.kind_of?(#{self.name}) \\
|
182
|
+
#{non_slots.collect { |a| " and @#{a} == b.#{a}" }.join}
|
183
|
+
end
|
184
|
+
EOF
|
185
|
+
|
186
|
+
req_cs =
|
187
|
+
@@children[:required].collect { |n|
|
188
|
+
", @#{n}.recursively(pre, post, :#{n}, &f)"
|
189
|
+
}.join
|
190
|
+
|
191
|
+
many_cs =
|
192
|
+
@@children[:many].collect { |n|
|
193
|
+
", @#{n}.each_with_index.collect { |n, i| n.recursively(pre, post, [:#{n}, i], &f) }"
|
194
|
+
}.join
|
195
|
+
|
196
|
+
opt_cs =
|
197
|
+
@@children[:optional].collect { |n, _|
|
198
|
+
", @#{n} ? @#{n}.recursively(pre, post, :#{n}, &f) : nil"
|
199
|
+
}.join
|
200
|
+
|
201
|
+
req_as =
|
202
|
+
(@@attributes[:required] + @@attributes[:many]).collect { |a|
|
203
|
+
", @#{a}"
|
204
|
+
}.join
|
205
|
+
|
206
|
+
opt_as = @@attributes[:optional].collect { |a, _|
|
207
|
+
", @#{a}"
|
208
|
+
}.join
|
209
|
+
|
210
|
+
req_ss =
|
211
|
+
(@@slots[:required] + @@slots[:many]).collect { |a|
|
212
|
+
", @#{a}"
|
213
|
+
}.join
|
214
|
+
|
215
|
+
opt_ss = @@slots[:optional].collect { |a, _|
|
216
|
+
", @#{a}"
|
217
|
+
}.join
|
218
|
+
|
219
|
+
class_eval <<EOF
|
220
|
+
def recursively(pre = nil, post = nil, context = nil, &f)
|
221
|
+
if pre and pre.arity == 2
|
222
|
+
stop = pre.call(self, context)
|
223
|
+
elsif pre
|
224
|
+
stop = pre.call(self)
|
225
|
+
else
|
226
|
+
stop = false
|
227
|
+
end
|
228
|
+
|
229
|
+
if stop
|
230
|
+
if f.arity == 2
|
231
|
+
res = f.call(self, context)
|
232
|
+
post.call(context) if post
|
233
|
+
return res
|
234
|
+
else
|
235
|
+
res = f.call(self)
|
236
|
+
post.call(context) if post
|
237
|
+
return res
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
recursed = #{self.name}.new(
|
242
|
+
@line#{req_cs + many_cs + req_as + req_ss + opt_cs + opt_as + opt_ss}
|
243
|
+
)
|
244
|
+
|
245
|
+
if f.arity == 2
|
246
|
+
res = f.call(recursed, context)
|
247
|
+
else
|
248
|
+
res = f.call(recursed)
|
249
|
+
end
|
250
|
+
|
251
|
+
post.call(context) if post
|
252
|
+
|
253
|
+
res
|
254
|
+
end
|
255
|
+
EOF
|
256
|
+
|
257
|
+
class_eval <<EOF
|
258
|
+
def bottom?
|
259
|
+
#{@@children.values.flatten(1).empty?.inspect}
|
260
|
+
end
|
261
|
+
EOF
|
262
|
+
|
263
|
+
attrs =
|
264
|
+
@@attributes[:required] + @@attributes[:many] +
|
265
|
+
@@attributes[:optional].collect(&:first)
|
266
|
+
|
267
|
+
class_eval <<EOF
|
268
|
+
def details
|
269
|
+
#{attrs.inspect}
|
270
|
+
end
|
271
|
+
EOF
|
272
|
+
|
273
|
+
slots =
|
274
|
+
@@slots[:required] + @@slots[:many] +
|
275
|
+
@@slots[:optional].collect(&:first)
|
276
|
+
|
277
|
+
class_eval <<EOF
|
278
|
+
def slots
|
279
|
+
#{slots.inspect}
|
280
|
+
end
|
281
|
+
EOF
|
282
|
+
|
283
|
+
required = @@children[:required].collect { |c| ", [:\"#{c}\", @#{c}.to_sexp]" }.join
|
284
|
+
many = @@children[:many].collect { |c| ", [:\"#{c}\", @#{c}.collect(&:to_sexp)]" }.join
|
285
|
+
optional = @@children[:optional].collect { |c, _| ", [:\"#{c}\", @#{c} && @#{c}.to_sexp]" }.join
|
286
|
+
|
287
|
+
a_required = @@attributes[:required].collect { |c| ", [:\"#{c}\", @#{c}]" }.join
|
288
|
+
a_many = @@attributes[:many].collect { |c| ", [:\"#{c}\", @#{c}]" }.join
|
289
|
+
a_optional = @@attributes[:optional].collect { |c, _| ", [:\"#{c}\", @#{c}]" }.join
|
290
|
+
|
291
|
+
class_eval <<EOF
|
292
|
+
def to_sexp
|
293
|
+
[:"#{self.name.split("::").last.downcase}"#{required}#{many}#{optional}#{a_required}#{a_many}#{a_optional}]
|
294
|
+
end
|
295
|
+
EOF
|
296
|
+
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
module NodeLike
|
301
|
+
attr_accessor :line
|
302
|
+
|
303
|
+
# yield this node's subnodes to a block recursively, and then itself
|
304
|
+
# override this if for nodes with children, ie lists
|
305
|
+
#
|
306
|
+
# stop = predicate to determine whether to stop at a node before
|
307
|
+
# recursing into its children
|
308
|
+
def recursively(stop = nil, &f)
|
309
|
+
f.call(self)
|
310
|
+
end
|
311
|
+
|
312
|
+
# used to construct this expression in a quasiquote
|
313
|
+
# g = generator, d = depth
|
314
|
+
#
|
315
|
+
# quasiquotes should increase depth, unquotes should decrease
|
316
|
+
# an unquote at depth 0 should push the unquote's contents rather
|
317
|
+
# than itself
|
318
|
+
def construct(g, d)
|
319
|
+
raise Rubinius::CompileError, "no #construct for #{self}"
|
320
|
+
end
|
321
|
+
|
322
|
+
def through_quotes(pre_ = nil, post_ = nil, &f)
|
323
|
+
depth = 0
|
324
|
+
|
325
|
+
pre = proc { |x, c|
|
326
|
+
(pre_ && pre_.call(*([x, c, depth][0, pre_.arity])) && depth == 0) || \
|
327
|
+
x.kind_of?(AST::QuasiQuote) || \
|
328
|
+
x.unquote?
|
329
|
+
}
|
330
|
+
|
331
|
+
rpre = proc { |x, c|
|
332
|
+
pre_ && pre_.call(*([x, c, 0][0, pre_.arity]))
|
333
|
+
}
|
334
|
+
|
335
|
+
post = proc { post_ && post_.call }
|
336
|
+
|
337
|
+
action = proc { |e, c|
|
338
|
+
if e.unquote?
|
339
|
+
depth -= 1
|
340
|
+
if depth == 0
|
341
|
+
depth += 1
|
342
|
+
u = e.expression.recursively(rpre, post_, :unquoted, &f)
|
343
|
+
next e.class.new(
|
344
|
+
e.line,
|
345
|
+
u
|
346
|
+
)
|
347
|
+
end
|
348
|
+
|
349
|
+
u = e.expression.recursively(pre, post, :expression, &action)
|
350
|
+
depth += 1
|
351
|
+
e.class.new(
|
352
|
+
e.line,
|
353
|
+
u
|
354
|
+
)
|
355
|
+
elsif e.kind_of?(Atomy::AST::QuasiQuote)
|
356
|
+
depth += 1
|
357
|
+
q = e.expression.recursively(pre, post, :expression, &action)
|
358
|
+
depth -= 1
|
359
|
+
Atomy::AST::QuasiQuote.new(
|
360
|
+
e.line,
|
361
|
+
q
|
362
|
+
)
|
363
|
+
else
|
364
|
+
if depth == 0
|
365
|
+
f.call(e)
|
366
|
+
else
|
367
|
+
e
|
368
|
+
end
|
369
|
+
end
|
370
|
+
}
|
371
|
+
|
372
|
+
recursively(pre, post, &action)
|
373
|
+
end
|
374
|
+
|
375
|
+
def unquote(d)
|
376
|
+
return unless d
|
377
|
+
d - 1
|
378
|
+
end
|
379
|
+
|
380
|
+
def quote(d)
|
381
|
+
return unless d
|
382
|
+
d + 1
|
383
|
+
end
|
384
|
+
|
385
|
+
def get(g)
|
386
|
+
g.push_cpath_top
|
387
|
+
self.class.name.split("::").each do |n|
|
388
|
+
g.find_const n.to_sym
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
def to_node
|
393
|
+
self
|
394
|
+
end
|
395
|
+
|
396
|
+
def to_send
|
397
|
+
Send.new(
|
398
|
+
@line,
|
399
|
+
Primitive.new(@line, :self),
|
400
|
+
[],
|
401
|
+
self,
|
402
|
+
nil,
|
403
|
+
nil,
|
404
|
+
true
|
405
|
+
)
|
406
|
+
end
|
407
|
+
|
408
|
+
def method_name
|
409
|
+
nil
|
410
|
+
end
|
411
|
+
|
412
|
+
def namespace_symbol
|
413
|
+
method_name && method_name.to_sym
|
414
|
+
end
|
415
|
+
|
416
|
+
def unquote?
|
417
|
+
false
|
418
|
+
end
|
419
|
+
|
420
|
+
def caller
|
421
|
+
Atomy::AST::Send.new(
|
422
|
+
@line,
|
423
|
+
self,
|
424
|
+
[],
|
425
|
+
Atomy::AST::Variable.new(@line, "call"),
|
426
|
+
nil,
|
427
|
+
nil
|
428
|
+
)
|
429
|
+
end
|
430
|
+
|
431
|
+
def expand
|
432
|
+
Atomy::Macro.expand(self)
|
433
|
+
end
|
434
|
+
|
435
|
+
def evaluate(onto = nil)
|
436
|
+
Atomy::Compiler.evaluate_node(self, onto, TOPLEVEL_BINDING)
|
437
|
+
end
|
438
|
+
|
439
|
+
def resolve
|
440
|
+
ns = Atomy::Namespace.get
|
441
|
+
return self if @namespace || !ns
|
442
|
+
|
443
|
+
case self
|
444
|
+
when Atomy::AST::Send, Atomy::AST::Variable,
|
445
|
+
Atomy::AST::BinarySend, Atomy::AST::Unary
|
446
|
+
y = dup
|
447
|
+
if n = ns.resolve(namespace_symbol)
|
448
|
+
y.namespace = n.to_s
|
449
|
+
else
|
450
|
+
y.namespace = "_"
|
451
|
+
end
|
452
|
+
y
|
453
|
+
else
|
454
|
+
self
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
def prepare
|
459
|
+
self
|
460
|
+
end
|
461
|
+
|
462
|
+
def compile(g)
|
463
|
+
prepare.bytecode(g)
|
464
|
+
end
|
465
|
+
|
466
|
+
def load_bytecode(g)
|
467
|
+
compile(g)
|
468
|
+
end
|
469
|
+
|
470
|
+
def to_pattern
|
471
|
+
expand.pattern
|
472
|
+
end
|
473
|
+
|
474
|
+
def as_message(send)
|
475
|
+
raise "unknown message name: #{self.to_sexp.inspect}"
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
class Node < Rubinius::AST::Node
|
480
|
+
include NodeLike
|
481
|
+
extend SentientNode
|
482
|
+
|
483
|
+
def bytecode(g)
|
484
|
+
raise "no #bytecode for #{self.class.name}"
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
488
|
+
class Tree
|
489
|
+
attr_accessor :nodes
|
490
|
+
|
491
|
+
def initialize(nodes)
|
492
|
+
@nodes = Array(nodes)
|
493
|
+
end
|
494
|
+
|
495
|
+
def bytecode(g)
|
496
|
+
@nodes.each { |n| n.compile(g) }
|
497
|
+
end
|
498
|
+
|
499
|
+
def collect
|
500
|
+
Tree.new(@nodes.collect { |n| yield n })
|
501
|
+
end
|
502
|
+
end
|
503
|
+
|
504
|
+
class Script < Rubinius::AST::Container
|
505
|
+
def initialize(body)
|
506
|
+
super body
|
507
|
+
@name = :__script__
|
508
|
+
end
|
509
|
+
|
510
|
+
def bytecode(g)
|
511
|
+
super(g)
|
512
|
+
|
513
|
+
container_bytecode(g) do
|
514
|
+
g.push_state self
|
515
|
+
|
516
|
+
load = g.new_label
|
517
|
+
start = g.new_label
|
518
|
+
done = g.new_label
|
519
|
+
|
520
|
+
g.push_cpath_top
|
521
|
+
g.find_const :Atomy
|
522
|
+
g.find_const :CodeLoader
|
523
|
+
g.send :reason, 0
|
524
|
+
g.push_literal :load
|
525
|
+
g.send :==, 1
|
526
|
+
g.git load
|
527
|
+
|
528
|
+
start.set!
|
529
|
+
@body.bytecode g
|
530
|
+
g.goto done
|
531
|
+
|
532
|
+
load.set!
|
533
|
+
Atomy::CodeLoader.when_load.each do |e, c|
|
534
|
+
if c
|
535
|
+
skip = g.new_label
|
536
|
+
|
537
|
+
g.push_cpath_top
|
538
|
+
g.find_const :Atomy
|
539
|
+
g.find_const :CodeLoader
|
540
|
+
g.send :compiled?, 0
|
541
|
+
g.git skip
|
542
|
+
|
543
|
+
e.load_bytecode(g)
|
544
|
+
g.pop
|
545
|
+
|
546
|
+
skip.set!
|
547
|
+
else
|
548
|
+
e.load_bytecode(g)
|
549
|
+
g.pop
|
550
|
+
end
|
551
|
+
end
|
552
|
+
g.goto start
|
553
|
+
|
554
|
+
done.set!
|
555
|
+
g.pop
|
556
|
+
g.push :true
|
557
|
+
g.ret
|
558
|
+
g.pop_state
|
559
|
+
end
|
560
|
+
end
|
561
|
+
end
|
562
|
+
end
|
563
|
+
end
|
564
|
+
|
565
|
+
class Object
|
566
|
+
def to_node
|
567
|
+
raise "not a node: #{self.inspect}"
|
568
|
+
end
|
569
|
+
end
|
570
|
+
|
571
|
+
class Integer
|
572
|
+
def to_node
|
573
|
+
Atomy::AST::Primitive.new -1, self
|
574
|
+
end
|
575
|
+
end
|
576
|
+
|
577
|
+
class String
|
578
|
+
def to_node
|
579
|
+
Atomy::AST::String.new -1, self
|
580
|
+
end
|
581
|
+
end
|
582
|
+
|
583
|
+
class Array
|
584
|
+
def to_node
|
585
|
+
Atomy::AST::List.new -1, collect(&:to_node)
|
586
|
+
end
|
587
|
+
end
|
588
|
+
|
589
|
+
class NilClass
|
590
|
+
def to_node
|
591
|
+
Atomy::AST::Primitive.new -1, :nil
|
592
|
+
end
|
593
|
+
end
|
594
|
+
|
595
|
+
class Symbol
|
596
|
+
def to_node
|
597
|
+
Atomy::AST::Particle.new -1, self
|
598
|
+
end
|
599
|
+
end
|