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.
Files changed (99) hide show
  1. data/COPYING +30 -0
  2. data/README.md +1 -0
  3. data/bin/atomy +134 -0
  4. data/kernel/block.ay +30 -0
  5. data/kernel/boot.ay +10 -0
  6. data/kernel/comparison.ay +61 -0
  7. data/kernel/concurrency.ay +84 -0
  8. data/kernel/condition.ay +277 -0
  9. data/kernel/control-flow.ay +222 -0
  10. data/kernel/cosmetics.ay +3 -0
  11. data/kernel/data-delta.ay +105 -0
  12. data/kernel/data.ay +56 -0
  13. data/kernel/define.ay +93 -0
  14. data/kernel/doc.ay +453 -0
  15. data/kernel/documentation.ay +135 -0
  16. data/kernel/dynamic.ay +42 -0
  17. data/kernel/errors.ay +6 -0
  18. data/kernel/format.ay +13 -0
  19. data/kernel/format/data.ay +89 -0
  20. data/kernel/format/formatter.ay +345 -0
  21. data/kernel/format/parser.ay +13 -0
  22. data/kernel/hashes.ay +39 -0
  23. data/kernel/io.ay +244 -0
  24. data/kernel/namespaces.ay +63 -0
  25. data/kernel/node.ay +48 -0
  26. data/kernel/operators.ay +28 -0
  27. data/kernel/particles.ay +53 -0
  28. data/kernel/patterns.ay +256 -0
  29. data/kernel/precision.ay +148 -0
  30. data/kernel/pretty.ay +283 -0
  31. data/kernel/repl.ay +140 -0
  32. data/kernel/therie.ay +204 -0
  33. data/lib/ast/binary_send.rb +44 -0
  34. data/lib/ast/block.rb +268 -0
  35. data/lib/ast/constant.rb +88 -0
  36. data/lib/ast/internal/assign.rb +19 -0
  37. data/lib/ast/internal/block_pass.rb +21 -0
  38. data/lib/ast/internal/catch.rb +247 -0
  39. data/lib/ast/internal/class.rb +30 -0
  40. data/lib/ast/internal/class_variable.rb +23 -0
  41. data/lib/ast/internal/define.rb +174 -0
  42. data/lib/ast/internal/ensure.rb +135 -0
  43. data/lib/ast/internal/file.rb +14 -0
  44. data/lib/ast/internal/global_variable.rb +20 -0
  45. data/lib/ast/internal/if_then_else.rb +24 -0
  46. data/lib/ast/internal/instance_variable.rb +17 -0
  47. data/lib/ast/internal/let_macro.rb +35 -0
  48. data/lib/ast/internal/macro_quote.rb +23 -0
  49. data/lib/ast/internal/match.rb +53 -0
  50. data/lib/ast/internal/module.rb +30 -0
  51. data/lib/ast/internal/pattern.rb +17 -0
  52. data/lib/ast/internal/return.rb +29 -0
  53. data/lib/ast/internal/set.rb +19 -0
  54. data/lib/ast/internal/singleton_class.rb +18 -0
  55. data/lib/ast/internal/splat.rb +14 -0
  56. data/lib/ast/internal/when.rb +24 -0
  57. data/lib/ast/list.rb +25 -0
  58. data/lib/ast/macro.rb +37 -0
  59. data/lib/ast/node.rb +599 -0
  60. data/lib/ast/operator.rb +21 -0
  61. data/lib/ast/particle.rb +13 -0
  62. data/lib/ast/primitive.rb +20 -0
  63. data/lib/ast/quasi_quote.rb +20 -0
  64. data/lib/ast/quote.rb +13 -0
  65. data/lib/ast/send.rb +104 -0
  66. data/lib/ast/splice.rb +32 -0
  67. data/lib/ast/string.rb +23 -0
  68. data/lib/ast/unary.rb +44 -0
  69. data/lib/ast/unquote.rb +45 -0
  70. data/lib/ast/variable.rb +64 -0
  71. data/lib/atomy.kpeg.rb +3995 -0
  72. data/lib/code_loader.rb +137 -0
  73. data/lib/compiler/compiler.rb +155 -0
  74. data/lib/compiler/stages.rb +81 -0
  75. data/lib/formatter.kpeg.rb +1394 -0
  76. data/lib/macros.rb +317 -0
  77. data/lib/method.rb +261 -0
  78. data/lib/namespace.rb +236 -0
  79. data/lib/parser.rb +28 -0
  80. data/lib/patterns.rb +276 -0
  81. data/lib/patterns/any.rb +21 -0
  82. data/lib/patterns/attribute.rb +59 -0
  83. data/lib/patterns/block_pass.rb +54 -0
  84. data/lib/patterns/constant.rb +33 -0
  85. data/lib/patterns/default.rb +44 -0
  86. data/lib/patterns/head_tail.rb +63 -0
  87. data/lib/patterns/list.rb +77 -0
  88. data/lib/patterns/match.rb +45 -0
  89. data/lib/patterns/named.rb +55 -0
  90. data/lib/patterns/named_class.rb +46 -0
  91. data/lib/patterns/named_global.rb +46 -0
  92. data/lib/patterns/named_instance.rb +46 -0
  93. data/lib/patterns/particle.rb +29 -0
  94. data/lib/patterns/quasi_quote.rb +184 -0
  95. data/lib/patterns/quote.rb +33 -0
  96. data/lib/patterns/singleton_class.rb +31 -0
  97. data/lib/patterns/splat.rb +57 -0
  98. data/lib/util.rb +37 -0
  99. metadata +164 -0
data/lib/namespace.rb ADDED
@@ -0,0 +1,236 @@
1
+ module Atomy
2
+ NAMESPACES = {}
3
+ NAMESPACE_DELIM = "_ns_"
4
+
5
+ def self.namespaced(ns, name)
6
+ return name.to_s if !ns or ns == "_"
7
+ ns.to_s + NAMESPACE_DELIM + name.to_s
8
+ end
9
+
10
+ def self.from_namespaced(resolved)
11
+ split = resolved.to_s.split(NAMESPACE_DELIM)
12
+ meth_name = split.pop
13
+ ns_name = !split.empty? && split.join(NAMESPACE_DELIM)
14
+ [ns_name, meth_name]
15
+ end
16
+
17
+ class Namespace
18
+ attr_reader :name, :using, :symbols
19
+
20
+ def initialize(name, using = [])
21
+ using = [:atomy] + using unless name == :atomy
22
+
23
+ @name = name
24
+ @using = using
25
+ @symbols = []
26
+ end
27
+
28
+ def register(sym)
29
+ @symbols << sym unless contains?(sym)
30
+ end
31
+
32
+ def contains?(sym)
33
+ @symbols.include?(sym)
34
+ end
35
+
36
+ def use(sym)
37
+ raise "namespace `#{sym}` tried to use itself" if sym == @name
38
+ raise "unknown namespace `#{sym}'" unless ns = Namespace.get(sym)
39
+ raise "circular namespaces: `#{@name}' <=> `#{sym}'" if ns.uses?(@name)
40
+ @using << sym unless @using.include?(sym)
41
+ end
42
+
43
+ def uses?(ns)
44
+ return true if @using.include?(ns)
45
+
46
+ @using.each do |u|
47
+ return true if Namespace.get(u).uses?(ns)
48
+ end
49
+
50
+ false
51
+ end
52
+
53
+ def resolve(sym)
54
+ return @name if contains?(sym)
55
+
56
+ @using.each do |ns|
57
+ unless used = Namespace.get(ns)
58
+ raise "unknown namespace: #{ns.inspect}"
59
+ end
60
+
61
+ return ns if used.contains?(sym)
62
+ end
63
+
64
+ nil
65
+ end
66
+
67
+ def top_down(&blk)
68
+ yield @name
69
+ @using.each do |u|
70
+ Atomy::Namespace.get(u).top_down(&blk)
71
+ end
72
+ nil
73
+ end
74
+
75
+ def self.define_target
76
+ Thread.current.atomy_get_local(:atomy_define_in) ||
77
+ get && get.name.to_s
78
+ end
79
+
80
+ def self.ensure(name, using = [])
81
+ Thread.current.atomy_set_local(
82
+ :atomy_namespace,
83
+ create(name, using)
84
+ )
85
+ end
86
+
87
+ def self.create(name, using = [])
88
+ NAMESPACES[name.to_sym] ||=
89
+ new(name, using)
90
+ end
91
+
92
+ def self.get(name = nil)
93
+ return NAMESPACES[name.to_sym] if name
94
+ Thread.current.atomy_get_local(:atomy_namespace)
95
+ end
96
+
97
+ def self.set(x)
98
+ Thread.current.atomy_set_local(:atomy_namespace, x)
99
+ end
100
+
101
+ def self.register(sym, name = nil)
102
+ ns = get(name)
103
+ return unless ns
104
+ ns.register(sym)
105
+ end
106
+
107
+ def self.name
108
+ ns = get
109
+ return unless ns
110
+ ns.name
111
+ end
112
+
113
+ def self.try_methods(name)
114
+ ns_name, meth_name = Atomy.from_namespaced(name)
115
+
116
+ if ns_name != "_" and \
117
+ ns = Atomy::Namespace.get(ns_name && ns_name.to_sym)
118
+ ns.top_down do |name|
119
+ yield Atomy.namespaced(name, meth_name).to_sym
120
+ end
121
+ end
122
+
123
+ meth_name.to_sym
124
+ end
125
+ end
126
+ end
127
+
128
+ class Thread
129
+ def atomy_get_local(n)
130
+ @locals[n]
131
+ end
132
+
133
+ def atomy_set_local(n, v)
134
+ @locals[n] = v
135
+ end
136
+ end
137
+
138
+ # NOTE: this is currently not used
139
+ # TODO: allow_private stuff
140
+ =begin
141
+ def Rubinius.bind_call(recv, nmeth, *args, &blk)
142
+ ns_name, meth_name = Atomy.from_namespaced(nmeth)
143
+
144
+ if ns_name == "_"
145
+ ns = nil
146
+ else
147
+ ns = Atomy::Namespace.get(!ns_name ? nil : ns_name.to_sym)
148
+ end
149
+
150
+ meth = meth_name.to_sym
151
+
152
+ res = Rubinius::CallUnit.send_as(meth)
153
+
154
+ if ns
155
+ nss = [ns]
156
+ scan = proc do |u|
157
+ unless un = Atomy::Namespace.get(u) and \
158
+ !nss.include?(un)
159
+ next
160
+ end
161
+
162
+ nss << un
163
+ un.using.each(&scan)
164
+ end
165
+
166
+ ns.using.each(&scan)
167
+
168
+ nss.reverse_each do |n|
169
+ next unless n.contains?(meth)
170
+ m = Atomy.namespaced(n.name, meth).to_sym
171
+ res = Rubinius::CallUnit.test(
172
+ Rubinius::CallUnit.test_respond_to(m),
173
+ Rubinius::CallUnit.send_as(m),
174
+ res
175
+ )
176
+ end
177
+ end
178
+
179
+ res
180
+ end
181
+ =end
182
+
183
+ class Object
184
+ alias :respond_to_atomy_old? :respond_to?
185
+
186
+ def respond_to?(nmeth, include_private = false)
187
+ return true if respond_to_atomy_old?(nmeth, include_private)
188
+
189
+ Atomy::Namespace.try_methods(nmeth) do |m|
190
+ return true if respond_to_atomy_old?(m, include_private)
191
+ end
192
+
193
+ false
194
+ end
195
+
196
+ def send(nmeth, *as, &blk)
197
+ if respond_to_atomy_old?(nmeth, true)
198
+ return __send__(nmeth, *as, &blk)
199
+ end
200
+
201
+ name = Atomy::Namespace.try_methods(nmeth) do |m|
202
+ if respond_to_atomy_old?(m, true)
203
+ return __send__(m, *as, &blk)
204
+ end
205
+ end
206
+
207
+ __send__(name, *as, &blk)
208
+ end
209
+
210
+ alias_method :atomy_send, :send
211
+
212
+ alias :method_atomy_old :method
213
+
214
+ def method(nmeth)
215
+ sym = Rubinius::Type.coerce_to_symbol nmeth
216
+ cm = Rubinius.find_method(self, sym)
217
+
218
+ return Method.new(self, cm[1], cm[0], sym) if cm
219
+
220
+ name = Atomy::Namespace.try_methods(nmeth) do |m|
221
+ cm = Rubinius.find_method(self, m)
222
+ return Method.new(self, cm[1], cm[0], m) if cm
223
+ end
224
+
225
+ method_atomy_old(name)
226
+ end
227
+ end
228
+
229
+ class Module
230
+ # TODO: alias_method, instance_method, module_function, private,
231
+ # private_class_method, protected, public, public_class_method
232
+ #
233
+ # TODO?: define_method, method_defined?, private_method_defined?,
234
+ # protected_method_defined?, public_method_defined?, remove_method,
235
+ # undef_method
236
+ end
data/lib/parser.rb ADDED
@@ -0,0 +1,28 @@
1
+ base = File.expand_path "../", __FILE__
2
+
3
+ require base + "/atomy.kpeg.rb"
4
+
5
+ module Atomy
6
+ class Parser
7
+ def self.parse_string(source)
8
+ p = new(source)
9
+ p.raise_error unless p.parse
10
+ AST::Tree.new(p.result)
11
+ end
12
+
13
+ def self.parse_file(name)
14
+ p = new(File.open(name, "rb").read)
15
+ p.raise_error unless p.parse
16
+ AST::Tree.new(p.result)
17
+ end
18
+ end
19
+
20
+ path = File.expand_path("../ast", __FILE__)
21
+
22
+ require path + "/node"
23
+
24
+ Dir["#{path}/**/*.rb"].sort.each do |f|
25
+ require f
26
+ end
27
+ end
28
+
data/lib/patterns.rb ADDED
@@ -0,0 +1,276 @@
1
+ class PatternMismatch < RuntimeError
2
+ def initialize(p)
3
+ @pattern = p
4
+ end
5
+ end
6
+
7
+ module Atomy::Patterns
8
+ class Pattern
9
+ attr_accessor :variable
10
+
11
+ # push the target class for this pattern in a defition
12
+ def target(g)
13
+ raise Rubinius::CompileError, "no #target for #{self}"
14
+ end
15
+
16
+ # test if the pattern mtaches the value at the top of the stack
17
+ # effect on the stack: top value removed, boolean pushed
18
+ def matches?(g)
19
+ raise Rubinius::CompileError, "no #matches? for #{self}"
20
+ end
21
+
22
+ # match the pattern on the value at the top of the stack
23
+ # effect on the stack: top value removed
24
+ def deconstruct(g, locals = {})
25
+ g.pop
26
+ end
27
+
28
+ # helper for pushing the current class const onto the stack
29
+ def get(g)
30
+ g.push_cpath_top
31
+ self.class.name.split("::").each do |n|
32
+ g.find_const n.to_sym
33
+ end
34
+ end
35
+
36
+ # create the pattern on the stack
37
+ def construct(g)
38
+ raise Rubinius::CompileError, "no #construct for #{self}"
39
+ end
40
+
41
+ def assign(g, expr, set = false)
42
+ locals = {}
43
+ local_names.each do |n|
44
+ locals[n] = Atomy.assign_local(g, n, set)
45
+ end
46
+
47
+ expr.compile(g)
48
+ g.dup
49
+ match(g, set, locals)
50
+ end
51
+
52
+ # try pattern-matching, erroring on failure
53
+ # effect on the stack: top value removed
54
+ def match(g, set = false, locals = {})
55
+ error = g.new_label
56
+ done = g.new_label
57
+
58
+ local_names.each do |n|
59
+ locals[n] ||= Atomy.assign_local(g, n, set)
60
+ end
61
+
62
+ g.dup
63
+ matches?(g)
64
+ g.gif error
65
+ deconstruct(g, locals)
66
+ g.goto done
67
+
68
+ error.set!
69
+ g.pop
70
+ g.push_self
71
+ g.push_const :PatternMismatch
72
+ construct(g)
73
+ g.send :new, 1
74
+ g.allow_private
75
+ g.send :raise, 1
76
+ g.pop
77
+
78
+ done.set!
79
+ end
80
+
81
+ # local names bound by this pattern
82
+ def local_names
83
+ []
84
+ end
85
+
86
+ # number of locals
87
+ def locals
88
+ local_names.size
89
+ end
90
+
91
+ # number of bindings
92
+ def bindings
93
+ locals
94
+ end
95
+
96
+ # test if a pattern matches a value
97
+ def ===(v)
98
+ singleton_class.dynamic_method(:===) do |g|
99
+ g.total_args = g.required_args = g.local_count = 1
100
+ g.push_local(0)
101
+ matches?(g)
102
+ g.ret
103
+ end
104
+
105
+ __send__ :===, v
106
+ end
107
+
108
+ def to_node
109
+ Atomy::AST::Pattern.new(0, self)
110
+ end
111
+ end
112
+
113
+ # include all pattern classes
114
+ path = File.expand_path("../patterns", __FILE__)
115
+
116
+ Dir["#{path}/*.rb"].sort.each do |f|
117
+ require path + "/#{File.basename f}"
118
+ end
119
+
120
+ class Atomy::AST::Node
121
+ def pattern
122
+ raise "unknown pattern: #{inspect}"
123
+ end
124
+ end
125
+
126
+ class Atomy::AST::Variable
127
+ def pattern
128
+ if @name == "_"
129
+ Any.new
130
+ else
131
+ Named.new(@name, Any.new)
132
+ end
133
+ end
134
+ end
135
+
136
+ class Atomy::AST::Primitive
137
+ def pattern
138
+ Match.new(@value)
139
+ end
140
+ end
141
+
142
+ class Atomy::AST::List
143
+ def pattern
144
+ List.new(@elements.collect(&:to_pattern))
145
+ end
146
+ end
147
+
148
+ class Atomy::AST::Constant
149
+ def pattern
150
+ Constant.new(self)
151
+ end
152
+ end
153
+
154
+ class Atomy::AST::ScopedConstant
155
+ def pattern
156
+ Constant.new(self)
157
+ end
158
+ end
159
+
160
+ class Atomy::AST::ToplevelConstant
161
+ def pattern
162
+ Constant.new(self)
163
+ end
164
+ end
165
+
166
+ class Atomy::AST::BinarySend
167
+ def pattern
168
+ case @operator
169
+ when "."
170
+ HeadTail.new(@lhs.to_pattern, @rhs.to_pattern)
171
+ when "="
172
+ Default.new(@lhs.to_pattern, @rhs)
173
+ when "?"
174
+ Predicate.new(@private ? Any.new : @lhs.to_pattern, @rhs)
175
+ end
176
+ end
177
+ end
178
+
179
+ class Atomy::AST::Assign
180
+ def pattern
181
+ Default.new(@lhs.to_pattern, @rhs)
182
+ end
183
+ end
184
+
185
+ class Atomy::AST::BlockPass
186
+ def pattern
187
+ BlockPass.new(@body.to_pattern)
188
+ end
189
+ end
190
+
191
+ class Atomy::AST::Quote
192
+ def pattern
193
+ Quote.new(@expression)
194
+ end
195
+ end
196
+
197
+ class Atomy::AST::Block
198
+ def pattern
199
+ SingletonClass.new(self)
200
+ end
201
+ end
202
+
203
+ class Atomy::AST::GlobalVariable
204
+ def pattern
205
+ NamedGlobal.new(@identifier)
206
+ end
207
+ end
208
+
209
+ class Atomy::AST::InstanceVariable
210
+ def pattern
211
+ NamedInstance.new(@identifier)
212
+ end
213
+ end
214
+
215
+ class Atomy::AST::ClassVariable
216
+ def pattern
217
+ NamedClass.new(@identifier)
218
+ end
219
+ end
220
+
221
+ class Atomy::AST::Unary
222
+ def pattern
223
+ case @operator
224
+ when "$"
225
+ NamedGlobal.new(@receiver.name)
226
+ when "@"
227
+ case @receiver
228
+ when Atomy::AST::Unary
229
+ NamedClass.new(@receiver.receiver.name)
230
+ else
231
+ NamedInstance.new(@receiver.name)
232
+ end
233
+ when "%"
234
+ RuntimeClass.new(@receiver, nil)
235
+ when "&"
236
+ BlockPass.new(@receiver.to_pattern)
237
+ when "*"
238
+ Splat.new(@receiver.to_pattern)
239
+ end
240
+ end
241
+ end
242
+
243
+ class Atomy::AST::Splat
244
+ def pattern
245
+ Splat.new(@value.to_pattern)
246
+ end
247
+ end
248
+
249
+ class Atomy::AST::String
250
+ def pattern
251
+ Match.new(@value)
252
+ end
253
+ end
254
+
255
+ class Atomy::AST::Particle
256
+ def pattern
257
+ Particle.new(@name.to_sym) # TODO: other forms
258
+ end
259
+ end
260
+
261
+ class Atomy::AST::Send
262
+ def pattern
263
+ if @block
264
+ Named.new(@method_name, @block.contents[0].to_pattern)
265
+ else
266
+ Attribute.new(@receiver, @method_name, @arguments)
267
+ end
268
+ end
269
+ end
270
+
271
+ class Atomy::AST::QuasiQuote
272
+ def pattern
273
+ QuasiQuote.new(self)
274
+ end
275
+ end
276
+ end