atomy 0.1.1 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (172) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +13 -0
  3. data/LICENSE.md +201 -0
  4. data/bin/atomy +16 -133
  5. data/kernel/array.ay +6 -0
  6. data/kernel/atomy.ay +18 -0
  7. data/kernel/condition.ay +171 -271
  8. data/kernel/control-flow.ay +197 -192
  9. data/kernel/core.ay +120 -0
  10. data/kernel/data.ay +83 -39
  11. data/kernel/define.ay +84 -93
  12. data/kernel/doc.ay +282 -449
  13. data/kernel/dynamic.ay +25 -29
  14. data/kernel/file.ay +9 -0
  15. data/kernel/grammar.ay +267 -0
  16. data/kernel/hash.ay +17 -0
  17. data/kernel/interpolation.ay +59 -0
  18. data/kernel/io.ay +70 -244
  19. data/kernel/let-macro.ay +24 -0
  20. data/kernel/let-pattern.ay +24 -0
  21. data/kernel/loop.ay +80 -0
  22. data/kernel/mutation.ay +53 -0
  23. data/kernel/particles.ay +176 -39
  24. data/kernel/patterns.ay +527 -191
  25. data/kernel/pretty.ay +311 -277
  26. data/kernel/quotes.ay +29 -0
  27. data/kernel/range.ay +4 -0
  28. data/kernel/regexp.ay +23 -0
  29. data/kernel/repl.ay +83 -109
  30. data/kernel/stack-local.ay +21 -0
  31. data/lib/atomy.rb +37 -0
  32. data/lib/atomy/bootstrap.rb +256 -0
  33. data/lib/atomy/code/assign.rb +64 -0
  34. data/lib/atomy/code/block.rb +98 -0
  35. data/lib/atomy/code/class_variable.rb +17 -0
  36. data/lib/atomy/code/constant.rb +21 -0
  37. data/lib/atomy/code/define.rb +242 -0
  38. data/lib/atomy/code/define_function.rb +51 -0
  39. data/lib/atomy/code/define_method.rb +20 -0
  40. data/lib/atomy/code/false.rb +9 -0
  41. data/lib/atomy/code/instance_variable.rb +15 -0
  42. data/lib/atomy/code/integer.rb +13 -0
  43. data/lib/atomy/code/list.rb +17 -0
  44. data/lib/atomy/code/nil.rb +9 -0
  45. data/lib/atomy/code/pattern.rb +23 -0
  46. data/lib/atomy/code/pattern/and.rb +61 -0
  47. data/lib/atomy/code/pattern/quasi_quote.rb +185 -0
  48. data/lib/atomy/code/pattern/splat.rb +29 -0
  49. data/lib/atomy/code/pattern/wildcard.rb +37 -0
  50. data/lib/atomy/code/quasi_quote.rb +118 -0
  51. data/lib/atomy/code/quote.rb +13 -0
  52. data/lib/atomy/code/self.rb +9 -0
  53. data/lib/atomy/code/send.rb +110 -0
  54. data/lib/atomy/code/sequence.rb +23 -0
  55. data/lib/atomy/code/string_literal.rb +53 -0
  56. data/lib/atomy/code/symbol.rb +13 -0
  57. data/lib/atomy/code/true.rb +9 -0
  58. data/lib/atomy/code/undefined.rb +9 -0
  59. data/lib/atomy/code/variable.rb +17 -0
  60. data/lib/atomy/codeloader.rb +218 -0
  61. data/lib/atomy/compiler.rb +57 -0
  62. data/lib/atomy/errors.rb +54 -0
  63. data/lib/atomy/grammar.rb +2278 -0
  64. data/lib/atomy/locals.rb +75 -0
  65. data/lib/atomy/message_structure.rb +277 -0
  66. data/lib/atomy/method.rb +343 -0
  67. data/lib/atomy/module.rb +144 -0
  68. data/lib/atomy/node/constructable.rb +169 -0
  69. data/lib/atomy/node/equality.rb +113 -0
  70. data/lib/atomy/node/meta.rb +206 -0
  71. data/lib/atomy/node/pretty.rb +108 -0
  72. data/lib/atomy/parser.rb +21 -0
  73. data/lib/atomy/pattern.rb +26 -0
  74. data/lib/atomy/pattern/and.rb +59 -0
  75. data/lib/atomy/pattern/attribute.rb +16 -0
  76. data/lib/atomy/pattern/class_variable.rb +15 -0
  77. data/lib/atomy/pattern/equality.rb +42 -0
  78. data/lib/atomy/pattern/instance_variable.rb +15 -0
  79. data/lib/atomy/pattern/kind_of.rb +20 -0
  80. data/lib/atomy/pattern/or.rb +48 -0
  81. data/lib/atomy/pattern/quasi_quote.rb +164 -0
  82. data/lib/atomy/pattern/splat.rb +15 -0
  83. data/lib/atomy/pattern/wildcard.rb +18 -0
  84. data/lib/atomy/rubygems.rb +48 -0
  85. data/lib/atomy/version.rb +3 -0
  86. metadata +169 -134
  87. data/COPYING +0 -30
  88. data/README.md +0 -1
  89. data/kernel/block.ay +0 -30
  90. data/kernel/boot.ay +0 -10
  91. data/kernel/comparison.ay +0 -61
  92. data/kernel/concurrency.ay +0 -84
  93. data/kernel/cosmetics.ay +0 -3
  94. data/kernel/data-delta.ay +0 -105
  95. data/kernel/documentation.ay +0 -135
  96. data/kernel/errors.ay +0 -6
  97. data/kernel/format.ay +0 -13
  98. data/kernel/format/data.ay +0 -89
  99. data/kernel/format/formatter.ay +0 -345
  100. data/kernel/format/parser.ay +0 -13
  101. data/kernel/hashes.ay +0 -39
  102. data/kernel/namespaces.ay +0 -63
  103. data/kernel/node.ay +0 -48
  104. data/kernel/operators.ay +0 -28
  105. data/kernel/precision.ay +0 -148
  106. data/kernel/therie.ay +0 -204
  107. data/lib/ast/binary_send.rb +0 -44
  108. data/lib/ast/block.rb +0 -268
  109. data/lib/ast/constant.rb +0 -88
  110. data/lib/ast/internal/assign.rb +0 -19
  111. data/lib/ast/internal/block_pass.rb +0 -21
  112. data/lib/ast/internal/catch.rb +0 -247
  113. data/lib/ast/internal/class.rb +0 -30
  114. data/lib/ast/internal/class_variable.rb +0 -23
  115. data/lib/ast/internal/define.rb +0 -174
  116. data/lib/ast/internal/ensure.rb +0 -135
  117. data/lib/ast/internal/file.rb +0 -14
  118. data/lib/ast/internal/global_variable.rb +0 -20
  119. data/lib/ast/internal/if_then_else.rb +0 -24
  120. data/lib/ast/internal/instance_variable.rb +0 -17
  121. data/lib/ast/internal/let_macro.rb +0 -35
  122. data/lib/ast/internal/macro_quote.rb +0 -23
  123. data/lib/ast/internal/match.rb +0 -53
  124. data/lib/ast/internal/module.rb +0 -30
  125. data/lib/ast/internal/pattern.rb +0 -17
  126. data/lib/ast/internal/return.rb +0 -29
  127. data/lib/ast/internal/set.rb +0 -19
  128. data/lib/ast/internal/singleton_class.rb +0 -18
  129. data/lib/ast/internal/splat.rb +0 -14
  130. data/lib/ast/internal/when.rb +0 -24
  131. data/lib/ast/list.rb +0 -25
  132. data/lib/ast/macro.rb +0 -37
  133. data/lib/ast/node.rb +0 -599
  134. data/lib/ast/operator.rb +0 -21
  135. data/lib/ast/particle.rb +0 -13
  136. data/lib/ast/primitive.rb +0 -20
  137. data/lib/ast/quasi_quote.rb +0 -20
  138. data/lib/ast/quote.rb +0 -13
  139. data/lib/ast/send.rb +0 -104
  140. data/lib/ast/splice.rb +0 -32
  141. data/lib/ast/string.rb +0 -23
  142. data/lib/ast/unary.rb +0 -44
  143. data/lib/ast/unquote.rb +0 -45
  144. data/lib/ast/variable.rb +0 -64
  145. data/lib/atomy.kpeg.rb +0 -3995
  146. data/lib/code_loader.rb +0 -137
  147. data/lib/compiler/compiler.rb +0 -155
  148. data/lib/compiler/stages.rb +0 -81
  149. data/lib/formatter.kpeg.rb +0 -1394
  150. data/lib/macros.rb +0 -317
  151. data/lib/method.rb +0 -261
  152. data/lib/namespace.rb +0 -236
  153. data/lib/parser.rb +0 -28
  154. data/lib/patterns.rb +0 -276
  155. data/lib/patterns/any.rb +0 -21
  156. data/lib/patterns/attribute.rb +0 -59
  157. data/lib/patterns/block_pass.rb +0 -54
  158. data/lib/patterns/constant.rb +0 -33
  159. data/lib/patterns/default.rb +0 -44
  160. data/lib/patterns/head_tail.rb +0 -63
  161. data/lib/patterns/list.rb +0 -77
  162. data/lib/patterns/match.rb +0 -45
  163. data/lib/patterns/named.rb +0 -55
  164. data/lib/patterns/named_class.rb +0 -46
  165. data/lib/patterns/named_global.rb +0 -46
  166. data/lib/patterns/named_instance.rb +0 -46
  167. data/lib/patterns/particle.rb +0 -29
  168. data/lib/patterns/quasi_quote.rb +0 -184
  169. data/lib/patterns/quote.rb +0 -33
  170. data/lib/patterns/singleton_class.rb +0 -31
  171. data/lib/patterns/splat.rb +0 -57
  172. data/lib/util.rb +0 -37
@@ -1,35 +0,0 @@
1
- module Atomy
2
- module AST
3
- class LetMacro < Node
4
- children :body, [:macros]
5
- generate
6
-
7
- def bytecode(g)
8
- pos(g)
9
-
10
- defined = {}
11
- @macros.each do |m|
12
- defined[m.pattern.method_name] =
13
- m.pattern.register_macro m.body, true
14
- end
15
-
16
- @body.compile(g)
17
-
18
- @macros.each do |m|
19
- name = defined[m.pattern.method_name]
20
-
21
- Atomy::Macro::Environment.singleton_class.remove_method(name)
22
-
23
- meth = Atomy::Macro::Environment.let[m.pattern.method_name]
24
- next unless meth && !meth.empty?
25
-
26
- Atomy::Macro::Environment.singleton_class.send(
27
- :define_method,
28
- name,
29
- meth.pop
30
- )
31
- end
32
- end
33
- end
34
- end
35
- end
@@ -1,23 +0,0 @@
1
- module Atomy
2
- module AST
3
- class MacroQuote < Node
4
- attributes :name, :contents, [:flags]
5
- generate
6
-
7
- def bytecode(g)
8
- pos(g)
9
- g.push_literal :impossible
10
- end
11
-
12
- def expand
13
- Atomy::Macro::Environment.quote(
14
- @name,
15
- @contents,
16
- @flags
17
- ).to_node
18
- end
19
-
20
- alias :prepare :expand
21
- end
22
- end
23
- end
@@ -1,53 +0,0 @@
1
- module Atomy
2
- module AST
3
- class Match < Node
4
- children :target, :body
5
- generate
6
-
7
- def bytecode(g)
8
- pos(g)
9
-
10
- done = g.new_label
11
-
12
- @target.compile(g)
13
-
14
- @body.contents.each do |e|
15
- MatchBranch.new(e.line, e.lhs, e.rhs).bytecode(g, done)
16
- end
17
-
18
- g.pop
19
- g.push_nil
20
-
21
- done.set!
22
- end
23
- end
24
-
25
- class MatchBranch < InlinedBody
26
- children :pattern, :branch
27
- generate
28
-
29
- def bytecode(g, done)
30
- pos(g)
31
-
32
- setup(g)
33
-
34
- skip = g.new_label
35
-
36
- pat = @pattern.to_pattern
37
- exp = @branch
38
-
39
- g.dup
40
- pat.matches?(g)
41
- g.gif skip
42
-
43
- pat.deconstruct(g)
44
- exp.compile(g)
45
- g.goto done
46
-
47
- skip.set!
48
-
49
- reset(g)
50
- end
51
- end
52
- end
53
- end
@@ -1,30 +0,0 @@
1
- module Atomy
2
- module AST
3
- class Module < Node
4
- children :name, :body
5
- generate
6
-
7
- def module_name
8
- case @name
9
- when Constant
10
- Rubinius::AST::ModuleName.new @line, @name.name
11
- when ToplevelConstant
12
- Rubinius::AST::ToplevelModuleName.new @line, @name
13
- when ScopedConstant
14
- Rubinius::AST::ScopedModuleName.new @line, @name
15
- else
16
- @name
17
- end
18
- end
19
-
20
- def module_body
21
- Rubinius::AST::ModuleScope.new @line, module_name, @body
22
- end
23
-
24
- def bytecode(g)
25
- module_name.bytecode(g)
26
- module_body.bytecode(g)
27
- end
28
- end
29
- end
30
- end
@@ -1,17 +0,0 @@
1
- module Atomy::AST
2
- class Pattern < Node
3
- attributes :pattern
4
- generate
5
-
6
- def construct(g, d = nil)
7
- get(g)
8
- g.push_int(@line)
9
- @pattern.construct(g)
10
- g.send :new, 2
11
- end
12
-
13
- def bytecode(g)
14
- @pattern.construct(g)
15
- end
16
- end
17
- end
@@ -1,29 +0,0 @@
1
- module Atomy
2
- module AST
3
- class Return < Node
4
- children :value
5
- generate
6
-
7
- def bytecode(g, force = false)
8
- if @value
9
- @value.compile(g)
10
- else
11
- g.push_nil
12
- end
13
-
14
- if lcl = g.state.rescue?
15
- g.push_stack_local lcl
16
- g.restore_exception_state
17
- end
18
-
19
- if g.state.block?
20
- g.raise_return
21
- elsif !force and g.state.ensure?
22
- g.ensure_return
23
- else
24
- g.ret
25
- end
26
- end
27
- end
28
- end
29
- end
@@ -1,19 +0,0 @@
1
- module Atomy
2
- module AST
3
- class Set < Node
4
- children :lhs, :rhs
5
- generate
6
-
7
- def bytecode(g)
8
- pos(g)
9
-
10
- if @lhs.respond_to?(:assign)
11
- @lhs.assign(g, @rhs)
12
- return
13
- end
14
-
15
- @lhs.to_pattern.assign(g, @rhs, true)
16
- end
17
- end
18
- end
19
- end
@@ -1,18 +0,0 @@
1
- module Atomy
2
- module AST
3
- class SingletonClass < Node
4
- children :receiver, :body
5
- generate
6
-
7
- def sclass_body
8
- Rubinius::AST::SClassScope.new @line, @body
9
- end
10
-
11
- def bytecode(g)
12
- pos(g)
13
- @receiver.compile(g)
14
- sclass_body.bytecode(g)
15
- end
16
- end
17
- end
18
- end
@@ -1,14 +0,0 @@
1
- module Atomy
2
- module AST
3
- class Splat < Node
4
- children :value
5
- generate
6
-
7
- def bytecode(g)
8
- pos(g)
9
- @value.compile(g)
10
- g.cast_array unless @value.kind_of?(List)
11
- end
12
- end
13
- end
14
- end
@@ -1,24 +0,0 @@
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 DELETED
@@ -1,25 +0,0 @@
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 DELETED
@@ -1,37 +0,0 @@
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 DELETED
@@ -1,599 +0,0 @@
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