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
@@ -0,0 +1,110 @@
|
|
1
|
+
module Atomy
|
2
|
+
module Code
|
3
|
+
class Send
|
4
|
+
attr_reader :receiver, :message, :arguments, :proc_argument, :block
|
5
|
+
|
6
|
+
def initialize(receiver, message, arguments = [], splat_argument = nil, proc_argument = nil, block = nil)
|
7
|
+
@receiver = receiver
|
8
|
+
@message = message
|
9
|
+
@arguments = arguments
|
10
|
+
@splat_argument = splat_argument
|
11
|
+
@proc_argument = proc_argument
|
12
|
+
@block = block
|
13
|
+
end
|
14
|
+
|
15
|
+
def bytecode(gen, mod)
|
16
|
+
if @receiver.nil? && fun = gen.state.scope.search_local(:"#{@message}:function")
|
17
|
+
invoke_function(gen, mod, fun)
|
18
|
+
else
|
19
|
+
invoke_method(gen, mod)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def invoke_function(gen, mod, fun)
|
26
|
+
fun.get_bytecode(gen)
|
27
|
+
|
28
|
+
gen.dup
|
29
|
+
gen.send(:block_env, 0)
|
30
|
+
gen.send(:constant_scope, 0)
|
31
|
+
gen.send(:module, 0)
|
32
|
+
|
33
|
+
gen.push_literal(@message)
|
34
|
+
|
35
|
+
gen.swap
|
36
|
+
|
37
|
+
gen.push_self
|
38
|
+
|
39
|
+
@arguments.each do |arg|
|
40
|
+
mod.compile(gen, arg)
|
41
|
+
end
|
42
|
+
gen.make_array(@arguments.size)
|
43
|
+
|
44
|
+
if @splat_argument
|
45
|
+
mod.compile(gen, @splat_argument)
|
46
|
+
gen.send(:+, 1)
|
47
|
+
end
|
48
|
+
|
49
|
+
if @proc_argument
|
50
|
+
push_proc_argument(gen, mod)
|
51
|
+
elsif @block
|
52
|
+
mod.compile(gen, @block)
|
53
|
+
else
|
54
|
+
gen.push_nil
|
55
|
+
end
|
56
|
+
|
57
|
+
gen.send(:invoke, 5)
|
58
|
+
end
|
59
|
+
|
60
|
+
def invoke_method(gen, mod)
|
61
|
+
if @receiver
|
62
|
+
mod.compile(gen, @receiver)
|
63
|
+
else
|
64
|
+
gen.push_self
|
65
|
+
end
|
66
|
+
|
67
|
+
@arguments.each do |arg|
|
68
|
+
mod.compile(gen, arg)
|
69
|
+
end
|
70
|
+
|
71
|
+
if @splat_argument
|
72
|
+
mod.compile(gen, @splat_argument)
|
73
|
+
if @proc_argument
|
74
|
+
push_proc_argument(gen, mod)
|
75
|
+
elsif @block
|
76
|
+
mod.compile(gen, @block)
|
77
|
+
else
|
78
|
+
gen.push_nil
|
79
|
+
end
|
80
|
+
gen.allow_private unless @receiver
|
81
|
+
gen.send_with_splat(@message, @arguments.size)
|
82
|
+
elsif @proc_argument
|
83
|
+
push_proc_argument(gen, mod)
|
84
|
+
gen.allow_private unless @receiver
|
85
|
+
gen.send_with_block(@message, @arguments.size)
|
86
|
+
elsif @block
|
87
|
+
mod.compile(gen, @block)
|
88
|
+
gen.allow_private unless @receiver
|
89
|
+
gen.send_with_block(@message, @arguments.size)
|
90
|
+
else
|
91
|
+
gen.allow_private unless @receiver
|
92
|
+
gen.send(@message, @arguments.size)
|
93
|
+
end
|
94
|
+
|
95
|
+
def push_proc_argument(gen, mod)
|
96
|
+
nil_proc_arg = gen.new_label
|
97
|
+
mod.compile(gen, @proc_argument)
|
98
|
+
gen.dup
|
99
|
+
gen.is_nil
|
100
|
+
gen.git(nil_proc_arg)
|
101
|
+
gen.push_cpath_top
|
102
|
+
gen.find_const(:Proc)
|
103
|
+
gen.swap
|
104
|
+
gen.send(:__from_block__, 1)
|
105
|
+
nil_proc_arg.set!
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Atomy
|
2
|
+
module Code
|
3
|
+
class Sequence
|
4
|
+
attr_reader :nodes
|
5
|
+
|
6
|
+
def initialize(nodes)
|
7
|
+
@nodes = nodes
|
8
|
+
end
|
9
|
+
|
10
|
+
def bytecode(gen, mod)
|
11
|
+
if @nodes.empty?
|
12
|
+
gen.push_nil
|
13
|
+
return
|
14
|
+
end
|
15
|
+
|
16
|
+
@nodes.each.with_index do |node, idx|
|
17
|
+
gen.pop unless idx == 0
|
18
|
+
mod.compile(gen, node)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Atomy
|
2
|
+
module Code
|
3
|
+
class StringLiteral
|
4
|
+
ESCAPES = {
|
5
|
+
"n" => "\n", "s" => "\s", "r" => "\r", "t" => "\t", "v" => "\v",
|
6
|
+
"f" => "\f", "b" => "\b", "a" => "\a", "e" => "\e", "\\" => "\\"
|
7
|
+
}
|
8
|
+
|
9
|
+
def initialize(value, raw = false)
|
10
|
+
@value = value
|
11
|
+
@raw = raw
|
12
|
+
end
|
13
|
+
|
14
|
+
def bytecode(gen, mod)
|
15
|
+
if @raw
|
16
|
+
gen.push_literal(@value)
|
17
|
+
else
|
18
|
+
gen.push_literal(process_escapes(@value))
|
19
|
+
end
|
20
|
+
|
21
|
+
gen.string_dup
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def process_escapes(str)
|
27
|
+
processed = str.dup
|
28
|
+
|
29
|
+
processed.gsub!(/\\[xX]([0-9a-fA-F]{1,5})/) do
|
30
|
+
[$1.to_i(16)].pack("U")
|
31
|
+
end
|
32
|
+
|
33
|
+
processed.gsub!(/\\(\d{1,6})/) do
|
34
|
+
[$1.to_i].pack("U")
|
35
|
+
end
|
36
|
+
|
37
|
+
processed.gsub!(/\\[oO]([0-7]{1,7})/) do
|
38
|
+
[$1.to_i(8)].pack("U")
|
39
|
+
end
|
40
|
+
|
41
|
+
processed.gsub!(/\\[uU]([0-9a-fA-F]{4})/) do
|
42
|
+
[$1.to_i(16)].pack("U")
|
43
|
+
end
|
44
|
+
|
45
|
+
processed.gsub!(/\\(.)/) do
|
46
|
+
ESCAPES[$1] || "\\#$1"
|
47
|
+
end
|
48
|
+
|
49
|
+
processed
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Atomy
|
2
|
+
module Code
|
3
|
+
class Variable
|
4
|
+
def initialize(name)
|
5
|
+
@name = name
|
6
|
+
end
|
7
|
+
|
8
|
+
def bytecode(gen, mod)
|
9
|
+
if local = gen.state.scope.search_local(@name)
|
10
|
+
local.get_bytecode(gen)
|
11
|
+
else
|
12
|
+
Send.new(nil, @name).bytecode(gen, mod)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
require "atomy/bootstrap"
|
2
|
+
require "atomy/compiler"
|
3
|
+
require "atomy/parser"
|
4
|
+
require "atomy/module"
|
5
|
+
|
6
|
+
module Atomy
|
7
|
+
module CodeLoader
|
8
|
+
LOADED_MODULES = {}
|
9
|
+
|
10
|
+
extend self
|
11
|
+
|
12
|
+
def load_map
|
13
|
+
@load_map ||= {}
|
14
|
+
end
|
15
|
+
|
16
|
+
Lock = Object.new
|
17
|
+
|
18
|
+
class RequireRequest
|
19
|
+
def initialize(map, key)
|
20
|
+
@map = map
|
21
|
+
@key = key
|
22
|
+
@for = nil
|
23
|
+
@module = nil
|
24
|
+
@loaded = false
|
25
|
+
@remove = true
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_accessor :module
|
29
|
+
|
30
|
+
def take!
|
31
|
+
lock
|
32
|
+
@for = Thread.current
|
33
|
+
end
|
34
|
+
|
35
|
+
def current_thread?
|
36
|
+
@for == Thread.current
|
37
|
+
end
|
38
|
+
|
39
|
+
def lock
|
40
|
+
Rubinius.lock(self)
|
41
|
+
end
|
42
|
+
|
43
|
+
def unlock
|
44
|
+
Rubinius.unlock(self)
|
45
|
+
end
|
46
|
+
|
47
|
+
def wait
|
48
|
+
Rubinius.synchronize(Lock) do
|
49
|
+
@remove = false
|
50
|
+
end
|
51
|
+
|
52
|
+
take!
|
53
|
+
|
54
|
+
Rubinius.synchronize(Lock) do
|
55
|
+
if @loaded
|
56
|
+
@map.delete @key
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
@loaded
|
61
|
+
end
|
62
|
+
|
63
|
+
def passed!
|
64
|
+
@loaded = true
|
65
|
+
end
|
66
|
+
|
67
|
+
def remove!
|
68
|
+
Rubinius.synchronize(Lock) do
|
69
|
+
if @loaded || @remove
|
70
|
+
@map.delete(@key)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
unlock
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def require(path)
|
79
|
+
file = find_source(path)
|
80
|
+
|
81
|
+
return super unless file
|
82
|
+
|
83
|
+
wait = false
|
84
|
+
req = nil
|
85
|
+
|
86
|
+
reqs = load_map
|
87
|
+
|
88
|
+
Rubinius.synchronize(Lock) do
|
89
|
+
if req = reqs[file]
|
90
|
+
return req.module if req.current_thread?
|
91
|
+
wait = true
|
92
|
+
else
|
93
|
+
req = RequireRequest.new(reqs, file)
|
94
|
+
reqs[file] = req
|
95
|
+
req.take!
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
if wait
|
100
|
+
if req.wait
|
101
|
+
# While waiting the code was loaded by another thread.
|
102
|
+
# We need to release the lock so other threads can continue too.
|
103
|
+
req.unlock
|
104
|
+
return req.module
|
105
|
+
end
|
106
|
+
|
107
|
+
# The other thread doing the lock raised an exception
|
108
|
+
# through the require, so we try and load it again here.
|
109
|
+
end
|
110
|
+
|
111
|
+
begin
|
112
|
+
mod = load_atomy(file)
|
113
|
+
else
|
114
|
+
req.module = mod
|
115
|
+
req.passed!
|
116
|
+
ensure
|
117
|
+
req.remove!
|
118
|
+
end
|
119
|
+
|
120
|
+
mod
|
121
|
+
end
|
122
|
+
|
123
|
+
def register_feature(file, mod)
|
124
|
+
LOADED_MODULES[file] = mod
|
125
|
+
$LOADED_FEATURES << file
|
126
|
+
end
|
127
|
+
|
128
|
+
def load_atomy(file)
|
129
|
+
if loaded?(file)
|
130
|
+
LOADED_MODULES[file]
|
131
|
+
else
|
132
|
+
_, mod = run_script(file)
|
133
|
+
register_feature(file, mod)
|
134
|
+
mod
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def run_script(path)
|
139
|
+
file = find_source(path)
|
140
|
+
|
141
|
+
raise LoadError, "no such file to load -- #{path}" unless file
|
142
|
+
|
143
|
+
mod = Atomy::Module.new { use(Atomy::Bootstrap) }
|
144
|
+
mod.file = file.to_sym
|
145
|
+
|
146
|
+
node = Atomy::Parser.parse_file(file)
|
147
|
+
|
148
|
+
res = evaluate_sequences(node, mod)
|
149
|
+
|
150
|
+
[res, mod]
|
151
|
+
end
|
152
|
+
|
153
|
+
def evaluate_sequences(n, mod)
|
154
|
+
if n.is_a?(Atomy::Grammar::AST::Sequence)
|
155
|
+
res = nil
|
156
|
+
|
157
|
+
n.nodes.each do |sub|
|
158
|
+
res = evaluate_sequences(sub, mod)
|
159
|
+
end
|
160
|
+
|
161
|
+
res
|
162
|
+
else
|
163
|
+
mod.evaluate(n, mod.compile_context)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def find_source(path, search_in = $LOAD_PATH)
|
168
|
+
if qualified?(path)
|
169
|
+
expanded = File.expand_path(path)
|
170
|
+
return expanded if File.file?(expanded)
|
171
|
+
|
172
|
+
expanded = "#{expanded}#{source_extension}"
|
173
|
+
return expanded if File.file?(expanded)
|
174
|
+
else
|
175
|
+
search_path(path, search_in)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def find_atomy_source(path, search_in = $LOAD_PATH)
|
180
|
+
path += source_extension unless path.end_with?(source_extension)
|
181
|
+
find_source(path)
|
182
|
+
end
|
183
|
+
|
184
|
+
private
|
185
|
+
|
186
|
+
def loaded?(file)
|
187
|
+
$LOADED_FEATURES.include?(file)
|
188
|
+
end
|
189
|
+
|
190
|
+
def source_extension
|
191
|
+
".ay"
|
192
|
+
end
|
193
|
+
|
194
|
+
def search_path(path, load_paths)
|
195
|
+
load_paths.each do |load_path|
|
196
|
+
if found = find_source("#{load_path}/#{path}")
|
197
|
+
return found
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
if found = find_source("#{kernel_path}/#{path}")
|
202
|
+
return found
|
203
|
+
end
|
204
|
+
|
205
|
+
nil
|
206
|
+
end
|
207
|
+
|
208
|
+
def kernel_path
|
209
|
+
@kernel_path ||= File.expand_path("../../../kernel", __FILE__)
|
210
|
+
end
|
211
|
+
|
212
|
+
# something that doesn't look like it should be grabbed from the load
|
213
|
+
# path
|
214
|
+
def qualified?(path)
|
215
|
+
path =~ /^([~\/]|\.\.?\/)/
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|