atomy 0.1.1 → 0.6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +13 -0
- data/LICENSE.md +201 -0
- data/bin/atomy +16 -133
- data/kernel/array.ay +6 -0
- data/kernel/atomy.ay +18 -0
- data/kernel/condition.ay +171 -271
- data/kernel/control-flow.ay +197 -192
- data/kernel/core.ay +120 -0
- data/kernel/data.ay +83 -39
- data/kernel/define.ay +84 -93
- data/kernel/doc.ay +282 -449
- data/kernel/dynamic.ay +25 -29
- data/kernel/file.ay +9 -0
- data/kernel/grammar.ay +267 -0
- data/kernel/hash.ay +17 -0
- data/kernel/interpolation.ay +59 -0
- data/kernel/io.ay +70 -244
- data/kernel/let-macro.ay +24 -0
- data/kernel/let-pattern.ay +24 -0
- data/kernel/loop.ay +80 -0
- data/kernel/mutation.ay +53 -0
- data/kernel/particles.ay +176 -39
- data/kernel/patterns.ay +527 -191
- data/kernel/pretty.ay +311 -277
- data/kernel/quotes.ay +29 -0
- data/kernel/range.ay +4 -0
- data/kernel/regexp.ay +23 -0
- data/kernel/repl.ay +83 -109
- data/kernel/stack-local.ay +21 -0
- data/lib/atomy.rb +37 -0
- data/lib/atomy/bootstrap.rb +256 -0
- data/lib/atomy/code/assign.rb +64 -0
- data/lib/atomy/code/block.rb +98 -0
- data/lib/atomy/code/class_variable.rb +17 -0
- data/lib/atomy/code/constant.rb +21 -0
- data/lib/atomy/code/define.rb +242 -0
- data/lib/atomy/code/define_function.rb +51 -0
- data/lib/atomy/code/define_method.rb +20 -0
- data/lib/atomy/code/false.rb +9 -0
- data/lib/atomy/code/instance_variable.rb +15 -0
- data/lib/atomy/code/integer.rb +13 -0
- data/lib/atomy/code/list.rb +17 -0
- data/lib/atomy/code/nil.rb +9 -0
- data/lib/atomy/code/pattern.rb +23 -0
- data/lib/atomy/code/pattern/and.rb +61 -0
- data/lib/atomy/code/pattern/quasi_quote.rb +185 -0
- data/lib/atomy/code/pattern/splat.rb +29 -0
- data/lib/atomy/code/pattern/wildcard.rb +37 -0
- data/lib/atomy/code/quasi_quote.rb +118 -0
- data/lib/atomy/code/quote.rb +13 -0
- data/lib/atomy/code/self.rb +9 -0
- data/lib/atomy/code/send.rb +110 -0
- data/lib/atomy/code/sequence.rb +23 -0
- data/lib/atomy/code/string_literal.rb +53 -0
- data/lib/atomy/code/symbol.rb +13 -0
- data/lib/atomy/code/true.rb +9 -0
- data/lib/atomy/code/undefined.rb +9 -0
- data/lib/atomy/code/variable.rb +17 -0
- data/lib/atomy/codeloader.rb +218 -0
- data/lib/atomy/compiler.rb +57 -0
- data/lib/atomy/errors.rb +54 -0
- data/lib/atomy/grammar.rb +2278 -0
- data/lib/atomy/locals.rb +75 -0
- data/lib/atomy/message_structure.rb +277 -0
- data/lib/atomy/method.rb +343 -0
- data/lib/atomy/module.rb +144 -0
- data/lib/atomy/node/constructable.rb +169 -0
- data/lib/atomy/node/equality.rb +113 -0
- data/lib/atomy/node/meta.rb +206 -0
- data/lib/atomy/node/pretty.rb +108 -0
- data/lib/atomy/parser.rb +21 -0
- data/lib/atomy/pattern.rb +26 -0
- data/lib/atomy/pattern/and.rb +59 -0
- data/lib/atomy/pattern/attribute.rb +16 -0
- data/lib/atomy/pattern/class_variable.rb +15 -0
- data/lib/atomy/pattern/equality.rb +42 -0
- data/lib/atomy/pattern/instance_variable.rb +15 -0
- data/lib/atomy/pattern/kind_of.rb +20 -0
- data/lib/atomy/pattern/or.rb +48 -0
- data/lib/atomy/pattern/quasi_quote.rb +164 -0
- data/lib/atomy/pattern/splat.rb +15 -0
- data/lib/atomy/pattern/wildcard.rb +18 -0
- data/lib/atomy/rubygems.rb +48 -0
- data/lib/atomy/version.rb +3 -0
- metadata +169 -134
- data/COPYING +0 -30
- data/README.md +0 -1
- data/kernel/block.ay +0 -30
- data/kernel/boot.ay +0 -10
- data/kernel/comparison.ay +0 -61
- data/kernel/concurrency.ay +0 -84
- data/kernel/cosmetics.ay +0 -3
- data/kernel/data-delta.ay +0 -105
- data/kernel/documentation.ay +0 -135
- data/kernel/errors.ay +0 -6
- data/kernel/format.ay +0 -13
- data/kernel/format/data.ay +0 -89
- data/kernel/format/formatter.ay +0 -345
- data/kernel/format/parser.ay +0 -13
- data/kernel/hashes.ay +0 -39
- data/kernel/namespaces.ay +0 -63
- data/kernel/node.ay +0 -48
- data/kernel/operators.ay +0 -28
- data/kernel/precision.ay +0 -148
- data/kernel/therie.ay +0 -204
- data/lib/ast/binary_send.rb +0 -44
- data/lib/ast/block.rb +0 -268
- data/lib/ast/constant.rb +0 -88
- data/lib/ast/internal/assign.rb +0 -19
- data/lib/ast/internal/block_pass.rb +0 -21
- data/lib/ast/internal/catch.rb +0 -247
- data/lib/ast/internal/class.rb +0 -30
- data/lib/ast/internal/class_variable.rb +0 -23
- data/lib/ast/internal/define.rb +0 -174
- data/lib/ast/internal/ensure.rb +0 -135
- data/lib/ast/internal/file.rb +0 -14
- data/lib/ast/internal/global_variable.rb +0 -20
- data/lib/ast/internal/if_then_else.rb +0 -24
- data/lib/ast/internal/instance_variable.rb +0 -17
- data/lib/ast/internal/let_macro.rb +0 -35
- data/lib/ast/internal/macro_quote.rb +0 -23
- data/lib/ast/internal/match.rb +0 -53
- data/lib/ast/internal/module.rb +0 -30
- data/lib/ast/internal/pattern.rb +0 -17
- data/lib/ast/internal/return.rb +0 -29
- data/lib/ast/internal/set.rb +0 -19
- data/lib/ast/internal/singleton_class.rb +0 -18
- data/lib/ast/internal/splat.rb +0 -14
- data/lib/ast/internal/when.rb +0 -24
- data/lib/ast/list.rb +0 -25
- data/lib/ast/macro.rb +0 -37
- data/lib/ast/node.rb +0 -599
- data/lib/ast/operator.rb +0 -21
- data/lib/ast/particle.rb +0 -13
- data/lib/ast/primitive.rb +0 -20
- data/lib/ast/quasi_quote.rb +0 -20
- data/lib/ast/quote.rb +0 -13
- data/lib/ast/send.rb +0 -104
- data/lib/ast/splice.rb +0 -32
- data/lib/ast/string.rb +0 -23
- data/lib/ast/unary.rb +0 -44
- data/lib/ast/unquote.rb +0 -45
- data/lib/ast/variable.rb +0 -64
- data/lib/atomy.kpeg.rb +0 -3995
- data/lib/code_loader.rb +0 -137
- data/lib/compiler/compiler.rb +0 -155
- data/lib/compiler/stages.rb +0 -81
- data/lib/formatter.kpeg.rb +0 -1394
- data/lib/macros.rb +0 -317
- data/lib/method.rb +0 -261
- data/lib/namespace.rb +0 -236
- data/lib/parser.rb +0 -28
- data/lib/patterns.rb +0 -276
- data/lib/patterns/any.rb +0 -21
- data/lib/patterns/attribute.rb +0 -59
- data/lib/patterns/block_pass.rb +0 -54
- data/lib/patterns/constant.rb +0 -33
- data/lib/patterns/default.rb +0 -44
- data/lib/patterns/head_tail.rb +0 -63
- data/lib/patterns/list.rb +0 -77
- data/lib/patterns/match.rb +0 -45
- data/lib/patterns/named.rb +0 -55
- data/lib/patterns/named_class.rb +0 -46
- data/lib/patterns/named_global.rb +0 -46
- data/lib/patterns/named_instance.rb +0 -46
- data/lib/patterns/particle.rb +0 -29
- data/lib/patterns/quasi_quote.rb +0 -184
- data/lib/patterns/quote.rb +0 -33
- data/lib/patterns/singleton_class.rb +0 -31
- data/lib/patterns/splat.rb +0 -57
- data/lib/util.rb +0 -37
data/lib/atomy/module.rb
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
require "atomy/compiler"
|
2
|
+
require "atomy/locals"
|
3
|
+
require "atomy/errors"
|
4
|
+
|
5
|
+
require "atomy/method"
|
6
|
+
|
7
|
+
module Atomy
|
8
|
+
class Module < ::Module
|
9
|
+
# [Symbol] Absolute path to the file the module was loaded from.
|
10
|
+
attr_reader :file
|
11
|
+
|
12
|
+
def file=(file)
|
13
|
+
@file = file
|
14
|
+
Rubinius::Type.set_module_name(self, File.basename(file.to_s).to_sym, Object)
|
15
|
+
end
|
16
|
+
|
17
|
+
# [Module] Modules users of this module should automatically use.
|
18
|
+
attr_reader :exported_modules
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
extend self
|
22
|
+
|
23
|
+
@exported_modules = []
|
24
|
+
|
25
|
+
# easy accessor for the current module via ConstantScope lookup
|
26
|
+
const_set(:Self, self)
|
27
|
+
|
28
|
+
super
|
29
|
+
end
|
30
|
+
|
31
|
+
def export(*modules)
|
32
|
+
@exported_modules.concat(modules)
|
33
|
+
end
|
34
|
+
|
35
|
+
def compile(gen, node)
|
36
|
+
gen.set_line(node.line) if node.respond_to?(:line) && node.line
|
37
|
+
|
38
|
+
expanded = node
|
39
|
+
while expanded.is_a?(Atomy::Grammar::AST::Node)
|
40
|
+
expanded = expand(expanded)
|
41
|
+
end
|
42
|
+
|
43
|
+
expanded.bytecode(gen, self)
|
44
|
+
rescue
|
45
|
+
puts "when compiling: #{node}"
|
46
|
+
raise
|
47
|
+
end
|
48
|
+
|
49
|
+
def evaluate(node, binding = nil)
|
50
|
+
binding ||=
|
51
|
+
Binding.setup(
|
52
|
+
Rubinius::VariableScope.of_sender,
|
53
|
+
Rubinius::CompiledCode.of_sender,
|
54
|
+
Rubinius::ConstantScope.of_sender,
|
55
|
+
self)
|
56
|
+
|
57
|
+
code = Atomy::Compiler.compile(
|
58
|
+
node,
|
59
|
+
self,
|
60
|
+
Atomy::EvalLocalState.new(binding.variables))
|
61
|
+
|
62
|
+
code.add_metadata :for_eval, true
|
63
|
+
|
64
|
+
block = Atomy::Compiler.construct_block(code, binding)
|
65
|
+
block.call
|
66
|
+
end
|
67
|
+
|
68
|
+
def require(path)
|
69
|
+
Atomy::CodeLoader.require(path)
|
70
|
+
end
|
71
|
+
|
72
|
+
def inspect
|
73
|
+
if @file
|
74
|
+
super.sub(/>$/, " #{@file}>")
|
75
|
+
else
|
76
|
+
super
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def use(mod)
|
81
|
+
extend mod
|
82
|
+
include mod
|
83
|
+
|
84
|
+
if mod.is_a?(self.class)
|
85
|
+
mod.exported_modules.each do |m|
|
86
|
+
use(m)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
mod
|
91
|
+
end
|
92
|
+
|
93
|
+
# Node -> (Node | Code)
|
94
|
+
def expand(node)
|
95
|
+
raise UnknownCode.new(node)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Node -> Code::Pattern
|
99
|
+
def pattern(node)
|
100
|
+
raise UnknownPattern.new(node)
|
101
|
+
end
|
102
|
+
|
103
|
+
def compile_context
|
104
|
+
return @compile_context if @compile_context
|
105
|
+
|
106
|
+
scope = Rubinius::ConstantScope.new(
|
107
|
+
self,
|
108
|
+
Rubinius::ConstantScope.new(Object))
|
109
|
+
|
110
|
+
meth = proc {}.block.compiled_code
|
111
|
+
meth.metadata = nil
|
112
|
+
meth.name = :__script__
|
113
|
+
meth.scope = scope
|
114
|
+
|
115
|
+
variables =
|
116
|
+
Rubinius::VariableScope.synthesize(
|
117
|
+
meth, self, nil, self, nil, Rubinius::Tuple.new(0))
|
118
|
+
|
119
|
+
if @file
|
120
|
+
script = meth.create_script
|
121
|
+
script.file_path = @file.to_s
|
122
|
+
script.data_path = File.expand_path(@file.to_s)
|
123
|
+
script.make_main!
|
124
|
+
|
125
|
+
scope.script = script
|
126
|
+
end
|
127
|
+
|
128
|
+
@compile_context = Binding.setup(variables, meth, scope)
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
# atomy module semantics are defined via 'extend self', but we have to
|
134
|
+
# make sure that later extends are added *after* self
|
135
|
+
#
|
136
|
+
# this ensures that modules a module use don't take priority over the
|
137
|
+
# module's own methods
|
138
|
+
def extend(mod)
|
139
|
+
return super if mod == self
|
140
|
+
|
141
|
+
mod.include_into(singleton_class.direct_superclass)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require "atomy/grammar"
|
2
|
+
|
3
|
+
module Atomy::Grammar::AST
|
4
|
+
class Node
|
5
|
+
def construct(gen)
|
6
|
+
raise "no #construct for #{self.class}"
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def push_node(gen, name)
|
12
|
+
gen.push_cpath_top
|
13
|
+
gen.find_const(:Atomy)
|
14
|
+
gen.find_const(:Grammar)
|
15
|
+
gen.find_const(:AST)
|
16
|
+
gen.find_const(name)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Sequence
|
21
|
+
def construct(gen)
|
22
|
+
push_node(gen, :Sequence)
|
23
|
+
@nodes.each do |node|
|
24
|
+
node.construct(gen)
|
25
|
+
end
|
26
|
+
gen.make_array(@nodes.size)
|
27
|
+
gen.send(:new, 1)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Number
|
32
|
+
def construct(gen)
|
33
|
+
push_node(gen, :Number)
|
34
|
+
gen.push_int(@value)
|
35
|
+
gen.send(:new, 1)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Literal
|
40
|
+
def construct(gen)
|
41
|
+
push_node(gen, :Literal)
|
42
|
+
gen.push_literal(@value)
|
43
|
+
gen.send(:new, 1)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Quote
|
48
|
+
def construct(gen)
|
49
|
+
push_node(gen, :Quote)
|
50
|
+
@node.construct(gen)
|
51
|
+
gen.send(:new, 1)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class QuasiQuote
|
56
|
+
def construct(gen)
|
57
|
+
push_node(gen, :QuasiQuote)
|
58
|
+
@node.construct(gen)
|
59
|
+
gen.send(:new, 1)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class Unquote
|
64
|
+
def construct(gen)
|
65
|
+
push_node(gen, :Unquote)
|
66
|
+
@node.construct(gen)
|
67
|
+
gen.send(:new, 1)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class Constant
|
72
|
+
def construct(gen)
|
73
|
+
push_node(gen, :Constant)
|
74
|
+
gen.push_literal(@text)
|
75
|
+
gen.send(:new, 1)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class Word
|
80
|
+
def construct(gen)
|
81
|
+
push_node(gen, :Word)
|
82
|
+
gen.push_literal(@text)
|
83
|
+
gen.send(:new, 1)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class Prefix
|
88
|
+
def construct(gen)
|
89
|
+
push_node(gen, :Prefix)
|
90
|
+
@node.construct(gen)
|
91
|
+
gen.push_literal(@operator)
|
92
|
+
gen.send(:new, 2)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class Postfix
|
97
|
+
def construct(gen)
|
98
|
+
push_node(gen, :Postfix)
|
99
|
+
@node.construct(gen)
|
100
|
+
gen.push_literal(@operator)
|
101
|
+
gen.send(:new, 2)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class Infix
|
106
|
+
def construct(gen)
|
107
|
+
push_node(gen, :Infix)
|
108
|
+
if @left
|
109
|
+
@left.construct(gen)
|
110
|
+
else
|
111
|
+
gen.push_nil
|
112
|
+
end
|
113
|
+
@right.construct(gen)
|
114
|
+
gen.push_literal(@operator)
|
115
|
+
gen.send(:new, 3)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class Block
|
120
|
+
def construct(gen)
|
121
|
+
push_node(gen, :Block)
|
122
|
+
@nodes.each do |node|
|
123
|
+
node.construct(gen)
|
124
|
+
end
|
125
|
+
gen.make_array(@nodes.size)
|
126
|
+
gen.send(:new, 1)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
class List
|
131
|
+
def construct(gen)
|
132
|
+
push_node(gen, :List)
|
133
|
+
@nodes.each do |node|
|
134
|
+
node.construct(gen)
|
135
|
+
end
|
136
|
+
gen.make_array(@nodes.size)
|
137
|
+
gen.send(:new, 1)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class Compose
|
142
|
+
def construct(gen)
|
143
|
+
push_node(gen, :Compose)
|
144
|
+
@left.construct(gen)
|
145
|
+
@right.construct(gen)
|
146
|
+
gen.send(:new, 2)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
class Apply
|
151
|
+
def construct(gen)
|
152
|
+
push_node(gen, :Apply)
|
153
|
+
@node.construct(gen)
|
154
|
+
@arguments.each do |node|
|
155
|
+
node.construct(gen)
|
156
|
+
end
|
157
|
+
gen.make_array(@arguments.size)
|
158
|
+
gen.send(:new, 2)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
class StringLiteral
|
163
|
+
def construct(gen)
|
164
|
+
push_node(gen, :StringLiteral)
|
165
|
+
gen.push_literal(@value)
|
166
|
+
gen.send(:new, 1)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require "atomy/grammar"
|
2
|
+
|
3
|
+
module Atomy::Grammar::AST
|
4
|
+
class Node
|
5
|
+
end
|
6
|
+
|
7
|
+
class Sequence
|
8
|
+
def ==(other)
|
9
|
+
super || other.is_a?(self.class) && @nodes == other.nodes
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Number
|
14
|
+
def ==(other)
|
15
|
+
super || other.is_a?(self.class) && @value == other.value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Literal
|
20
|
+
def ==(other)
|
21
|
+
super || other.is_a?(self.class) && @value == other.value
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Quote
|
26
|
+
def ==(other)
|
27
|
+
super || other.is_a?(self.class) && @node == other.node
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class QuasiQuote
|
32
|
+
def ==(other)
|
33
|
+
super || other.is_a?(self.class) && @node == other.node
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Unquote
|
38
|
+
def ==(other)
|
39
|
+
super || other.is_a?(self.class) && @node == other.node
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Constant
|
44
|
+
def ==(other)
|
45
|
+
super || other.is_a?(self.class) && @text == other.text
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Word
|
50
|
+
def ==(other)
|
51
|
+
super || other.is_a?(self.class) && @text == other.text
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class Prefix
|
56
|
+
def ==(other)
|
57
|
+
super || other.is_a?(self.class) && \
|
58
|
+
@operator == other.operator && \
|
59
|
+
@node == other.node
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class Postfix
|
64
|
+
def ==(other)
|
65
|
+
super || other.is_a?(self.class) && \
|
66
|
+
@operator == other.operator && \
|
67
|
+
@node == other.node
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class Infix
|
72
|
+
def ==(other)
|
73
|
+
super || other.is_a?(self.class) && \
|
74
|
+
@operator == other.operator && \
|
75
|
+
@left == other.left && \
|
76
|
+
@right == other.right
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class Block
|
81
|
+
def ==(other)
|
82
|
+
super || other.is_a?(self.class) && @nodes == other.nodes
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class List
|
87
|
+
def ==(other)
|
88
|
+
super || other.is_a?(self.class) && @nodes == other.nodes
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class Compose
|
93
|
+
def ==(other)
|
94
|
+
super || other.is_a?(self.class) && \
|
95
|
+
@left == other.left && \
|
96
|
+
@right == other.right
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class Apply
|
101
|
+
def ==(other)
|
102
|
+
super || other.is_a?(self.class) && \
|
103
|
+
@node == other.node && \
|
104
|
+
@arguments == other.arguments
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class StringLiteral
|
109
|
+
def ==(other)
|
110
|
+
super || other.is_a?(self.class) && @value == other.value
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,206 @@
|
|
1
|
+
module Atomy::Grammar::AST
|
2
|
+
class Node
|
3
|
+
class << self
|
4
|
+
def basename
|
5
|
+
@basename ||= name.split("::").last.to_sym
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def each_child
|
10
|
+
end
|
11
|
+
|
12
|
+
def each_attribute
|
13
|
+
end
|
14
|
+
|
15
|
+
def children
|
16
|
+
names = []
|
17
|
+
|
18
|
+
each_child do |name, _|
|
19
|
+
names << name
|
20
|
+
end
|
21
|
+
|
22
|
+
names
|
23
|
+
end
|
24
|
+
|
25
|
+
def attributes
|
26
|
+
names = []
|
27
|
+
|
28
|
+
each_attribute do |name, _|
|
29
|
+
names << name
|
30
|
+
end
|
31
|
+
|
32
|
+
names
|
33
|
+
end
|
34
|
+
|
35
|
+
def accept(x)
|
36
|
+
name = :"visit_#{self.class.basename.downcase}"
|
37
|
+
|
38
|
+
if x.respond_to?(name)
|
39
|
+
x.send(name, self)
|
40
|
+
else
|
41
|
+
x.visit(self)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Recreate the node, calling the block for sub-nodes and using its return
|
46
|
+
# value in place of the node
|
47
|
+
def through
|
48
|
+
dup
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class Sequence
|
53
|
+
def each_child
|
54
|
+
yield :nodes, @nodes
|
55
|
+
end
|
56
|
+
|
57
|
+
def through
|
58
|
+
self.class.new(nodes.collect { |n| yield n })
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class Number
|
63
|
+
def each_attribute
|
64
|
+
yield :value, @value
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class Literal
|
69
|
+
def each_attribute
|
70
|
+
yield :value, @value
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class Quote
|
75
|
+
def each_child
|
76
|
+
yield :node, @node
|
77
|
+
end
|
78
|
+
|
79
|
+
def through
|
80
|
+
self.class.new(yield @node)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class QuasiQuote
|
85
|
+
def each_child
|
86
|
+
yield :node, @node
|
87
|
+
end
|
88
|
+
|
89
|
+
def through
|
90
|
+
self.class.new(yield @node)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class Unquote
|
95
|
+
def each_child
|
96
|
+
yield :node, @node
|
97
|
+
end
|
98
|
+
|
99
|
+
def through
|
100
|
+
self.class.new(yield @node)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
class Constant
|
105
|
+
def each_attribute
|
106
|
+
yield :text, @text
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class Word
|
111
|
+
def each_attribute
|
112
|
+
yield :text, @text
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
class Prefix
|
117
|
+
def each_attribute
|
118
|
+
yield :operator, @operator
|
119
|
+
end
|
120
|
+
|
121
|
+
def each_child
|
122
|
+
yield :node, @node
|
123
|
+
end
|
124
|
+
|
125
|
+
def through
|
126
|
+
self.class.new(yield(@node), @operator)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
class Postfix
|
131
|
+
def each_attribute
|
132
|
+
yield :operator, @operator
|
133
|
+
end
|
134
|
+
|
135
|
+
def each_child
|
136
|
+
yield :node, @node
|
137
|
+
end
|
138
|
+
|
139
|
+
def through
|
140
|
+
self.class.new(yield(@node), @operator)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class Infix
|
145
|
+
def each_attribute
|
146
|
+
yield :operator, @operator
|
147
|
+
end
|
148
|
+
|
149
|
+
def each_child
|
150
|
+
yield :left, @left if @left
|
151
|
+
yield :right, @right
|
152
|
+
end
|
153
|
+
|
154
|
+
def through
|
155
|
+
self.class.new(@left && yield(@left), yield(@right), @operator)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
class Block
|
160
|
+
def each_child
|
161
|
+
yield :nodes, @nodes
|
162
|
+
end
|
163
|
+
|
164
|
+
def through
|
165
|
+
self.class.new(@nodes.collect { |n| yield n })
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
class List
|
170
|
+
def each_child
|
171
|
+
yield :nodes, @nodes
|
172
|
+
end
|
173
|
+
|
174
|
+
def through
|
175
|
+
self.class.new(@nodes.collect { |n| yield n })
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
class Compose
|
180
|
+
def each_child
|
181
|
+
yield :left, @left
|
182
|
+
yield :right, @right
|
183
|
+
end
|
184
|
+
|
185
|
+
def through
|
186
|
+
self.class.new(yield(@left), yield(@right))
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
class Apply
|
191
|
+
def each_child
|
192
|
+
yield :node, @node
|
193
|
+
yield :arguments, @arguments
|
194
|
+
end
|
195
|
+
|
196
|
+
def through
|
197
|
+
self.class.new(yield(@node), @arguments.collect { |a| yield a })
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
class StringLiteral
|
202
|
+
def each_attribute
|
203
|
+
yield :value, @value
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|