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/kernel/quotes.ay
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
use(require("core"))
|
2
|
+
use(require("define"))
|
3
|
+
use(require("control-flow"))
|
4
|
+
|
5
|
+
macro(macro-quoter(~n) [~*as]: ~*body):
|
6
|
+
strpat = Unquote new('(string-literal & StringLiteral))
|
7
|
+
argpat = Unquote new('*args)
|
8
|
+
|
9
|
+
`({
|
10
|
+
quoter = [~*as]: ~*body
|
11
|
+
|
12
|
+
macro(~n ~strpat):
|
13
|
+
quoter call(string-literal value, [], evaluate(string-literal))
|
14
|
+
|
15
|
+
macro(~n (~strpat)(~argpat)):
|
16
|
+
quoter call(string-literal value, args collect &.text, evaluate(string-literal))
|
17
|
+
} call)
|
18
|
+
|
19
|
+
|
20
|
+
macro-quoter(w) [_, _, v]:
|
21
|
+
`[~*(v split collect [s]: Atomy Grammar AST StringLiteral new(s))]
|
22
|
+
|
23
|
+
macro-quoter(s) [_, _, v]:
|
24
|
+
`[~*(v split collect [s]:
|
25
|
+
if(s =~ Regexp new("[\p{Ll}_]", Regexp KCODE_UTF8))
|
26
|
+
then: `.~(Atomy Grammar AST Word new(s tr("-", "_") to-sym))
|
27
|
+
else: `.~(Atomy Grammar AST Word new(s to-sym)))]
|
28
|
+
|
29
|
+
macro-quoter(raw) [r]: Atomy Code StringLiteral new(r, true)
|
data/kernel/range.ay
ADDED
data/kernel/regexp.ay
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
use(require("core"))
|
2
|
+
use(require("define"))
|
3
|
+
use(require("quotes"))
|
4
|
+
use(require("control-flow"))
|
5
|
+
use(require("mutation"))
|
6
|
+
interpolate = require("interpolation")
|
7
|
+
|
8
|
+
macro-quoter(r) [r, fs]:
|
9
|
+
flags = 0
|
10
|
+
|
11
|
+
when(fs include?(.m)):
|
12
|
+
flags |= Regexp MULTILINE
|
13
|
+
|
14
|
+
when(fs include?(.i)):
|
15
|
+
flags |= Regexp IGNORECASE
|
16
|
+
|
17
|
+
when(fs include?(.x)):
|
18
|
+
flags |= Regexp EXTENDED
|
19
|
+
|
20
|
+
-- UTF8 by default
|
21
|
+
flags |= Regexp KCODE_UTF8
|
22
|
+
|
23
|
+
`(//Regexp new(~(interpolate interpolated(r)), ~(Atomy Grammar AST Number new(flags))))
|
data/kernel/repl.ay
CHANGED
@@ -1,140 +1,114 @@
|
|
1
|
-
|
1
|
+
use(require("atomy"))
|
2
2
|
|
3
|
-
|
3
|
+
use(require("doc"))
|
4
|
+
condition = use(require("condition"))
|
5
|
+
pretty = require("pretty")
|
4
6
|
|
5
7
|
require("readline")
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
restart available. Invoke this restart and pass along a string to \
|
14
|
-
override the prompt, which defaults to \code{>>}.
|
9
|
+
fn(try(source, module, debug = false)):
|
10
|
+
with-restarts(
|
11
|
+
retry: try(source, module)
|
12
|
+
abort: .ok):
|
13
|
+
condition signal(.evaluated(module evaluate(Atomy Parser parse-string(source), module compile-context))) rescue:
|
14
|
+
(e & (StandardError | ScriptError)): error(e)
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
fn(basic-repl(module, debug = false)):
|
17
|
+
loop:
|
18
|
+
prompt =
|
19
|
+
with-restarts(use-prompt(p): p):
|
20
|
+
condition signal(.prompt)
|
21
|
+
">> "
|
19
22
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
When the user enters code, \hl{#input(\italic{text})} is signaled. The code\
|
24
|
-
is evaluated with two restarts registered: \code{#retry} for re-attempting \
|
25
|
-
evaluation, and \code{#abort}, for canceling the evaluation. After the code\
|
26
|
-
is evaluated, \hl{#evaluated(\italic{result})} is signaled.
|
23
|
+
input =
|
24
|
+
Readline readline(prompt, true) rescue:
|
25
|
+
Interrupt: condition signal(.quit), ""
|
27
26
|
|
28
|
-
|
29
|
-
|
30
|
-
" spec {
|
31
|
-
bnd is-a?(Binding)
|
32
|
-
} for:
|
33
|
-
basic-repl(bnd = TOPLEVEL_BINDING) :=
|
34
|
-
loop:
|
35
|
-
prompt =
|
36
|
-
with-restarts(use-prompt(p) -> p):
|
37
|
-
signal(#prompt)
|
38
|
-
">> "
|
27
|
+
input match:
|
28
|
+
nil: condition signal(.quit)
|
39
29
|
|
40
|
-
|
41
|
-
{ Readline readline(prompt)
|
42
|
-
} rescue:
|
43
|
-
Interrupt -> do { signal(#quit), "" }
|
30
|
+
"": .ok
|
44
31
|
|
45
|
-
|
46
|
-
|
32
|
+
(String & { =~ r"^:[[:alnum:]]" }):
|
33
|
+
condition signal(.special(input[1 .. -1]))
|
47
34
|
|
48
|
-
|
35
|
+
source:
|
36
|
+
condition signal(.input(source))
|
37
|
+
try(source, module, debug)
|
49
38
|
|
50
|
-
|
51
|
-
signal(#special(in [1 .. -1]))
|
39
|
+
condition signal(.loop)
|
52
40
|
|
53
|
-
source -> do:
|
54
|
-
signal(#input(source))
|
55
41
|
|
56
|
-
|
57
|
-
with-restarts(retry -> try [], abort -> #ok):
|
58
|
-
res = Atomy::Compiler evaluate(source, bnd)
|
59
|
-
signal(#evaluated(res))
|
60
|
-
}
|
42
|
+
condition DefaultDebugger data(ReplDebugger(@error))
|
61
43
|
|
62
|
-
|
44
|
+
ReplDebugger open:
|
45
|
+
attr-accessor(.module)
|
63
46
|
|
64
|
-
|
47
|
+
def(ReplDebugger run):
|
48
|
+
condition signal(.debug(self))
|
65
49
|
|
50
|
+
show-banner
|
66
51
|
|
67
|
-
|
68
|
-
|
69
|
-
results along with a number, allow the user to continue evaluating code, \
|
70
|
-
and once they enter a \italic{special command} in the form of \
|
71
|
-
\code{:\italic{number}}, the specified restart will be invoked.
|
72
|
-
" for:
|
73
|
-
class(ReplDebugger):
|
74
|
-
class(<< self):
|
75
|
-
show-backtrace(e) := do:
|
76
|
-
Rubinius::Backtrace backtrace(e backtrace) _/show print
|
77
|
-
debug(e)
|
52
|
+
with-restarts(backtrace: show-backtrace):
|
53
|
+
debug
|
78
54
|
|
79
|
-
|
80
|
-
|
55
|
+
def(ReplDebugger(e) show-banner):
|
56
|
+
puts("-" * 78)
|
57
|
+
i"#{e name}: #{e message}" split("\n") each [l]:
|
58
|
+
puts(i"*** #{l}")
|
81
59
|
|
82
|
-
|
83
|
-
|
60
|
+
def(ReplDebugger debug):
|
61
|
+
show-restarts
|
84
62
|
|
85
|
-
|
86
|
-
|
63
|
+
basic-repl(@module) bind:
|
64
|
+
.prompt: condition restart(.use-prompt, "[!]> ")
|
87
65
|
|
88
|
-
|
89
|
-
|
66
|
+
.special(n & { =~ r"\d+" }):
|
67
|
+
^(condition Restarts) [n to-i] invoke
|
90
68
|
|
91
|
-
|
92
|
-
^restarts [n to-i] invoke
|
69
|
+
.quit: exit(1)
|
93
70
|
|
94
|
-
#quit -> exit(1)
|
95
71
|
|
96
|
-
|
72
|
+
def(repl(history = nil, module = nil, debug = false)):
|
73
|
+
unless(module):
|
74
|
+
&module = Atomy Module new
|
75
|
+
module file = ."(repl)"
|
76
|
+
module use(require("atomy"))
|
97
77
|
|
98
|
-
|
99
|
-
|
100
|
-
|
78
|
+
when(history && File exists?(history)):
|
79
|
+
File open(history, "r") [f]:
|
80
|
+
f readlines each [l]:
|
81
|
+
Readline HISTORY << l strip
|
101
82
|
|
102
|
-
|
103
|
-
upon termination.
|
104
|
-
" spec {
|
105
|
-
history is-a?(String)
|
106
|
-
bnd is-a?(Binding)
|
107
|
-
} for:
|
108
|
-
repl(history = nil, bnd = TOPLEVEL_BINDING) := do:
|
109
|
-
when(history && File exists?(history)):
|
110
|
-
File open(history, "r") [f]:
|
111
|
-
f readlines each [l]:
|
112
|
-
Readline::HISTORY << l strip
|
113
|
-
|
114
|
-
SANE_HISTORY = []
|
83
|
+
sane-history = []
|
115
84
|
|
116
|
-
|
117
|
-
|
85
|
+
with(condition Debugger = ReplDebugger) {
|
86
|
+
frame = 0
|
118
87
|
|
119
|
-
|
120
|
-
|
121
|
-
}
|
122
|
-
#prompt ->
|
123
|
-
restart(#use-prompt, "[" + frame to-s + "]> ")
|
124
|
-
|
125
|
-
#loop ->
|
126
|
-
(frame += 1)
|
88
|
+
basic-repl(module, debug) bind:
|
89
|
+
.prompt:
|
90
|
+
restart(.use-prompt, i"[#{frame}]> ")
|
127
91
|
|
128
|
-
|
129
|
-
|
130
|
-
#input(str) -> (SANE_HISTORY << str)
|
92
|
+
.loop:
|
93
|
+
frame += 1
|
131
94
|
|
132
|
-
|
133
|
-
|
95
|
+
.quit:
|
96
|
+
exit(0)
|
134
97
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
98
|
+
.input(str):
|
99
|
+
sane-history << str
|
100
|
+
|
101
|
+
.special(String & { == "h" }):
|
102
|
+
puts(":h\thelp")
|
103
|
+
|
104
|
+
.debug(dbg):
|
105
|
+
dbg module = module
|
106
|
+
|
107
|
+
.evaluated(r):
|
108
|
+
with(pretty Multiline = true,
|
109
|
+
pretty Colored = true):
|
110
|
+
puts((text(" =>") <+> pretty doc(r)) render(56))
|
111
|
+
} ensuring:
|
112
|
+
when(history):
|
113
|
+
File open(history, "a") [f]:
|
114
|
+
f puts(*sane-history)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
use(require("core"))
|
2
|
+
use(require("define"))
|
3
|
+
use(require("control-flow"))
|
4
|
+
use(require("patterns"))
|
5
|
+
|
6
|
+
class(Local):
|
7
|
+
class(Setter):
|
8
|
+
def(initialize(@local, @code)) {}
|
9
|
+
|
10
|
+
def(bytecode(gen, mod)):
|
11
|
+
mod compile(gen, @code)
|
12
|
+
gen set-stack-local(@local allocate(gen))
|
13
|
+
|
14
|
+
def(bytecode(gen, mod)):
|
15
|
+
gen push-stack-local(allocate(gen))
|
16
|
+
|
17
|
+
def(allocate(gen)):
|
18
|
+
@stack-local = (@stack-local || gen new-stack-local)
|
19
|
+
|
20
|
+
def(set(code)):
|
21
|
+
Setter new(self, code)
|
data/lib/atomy.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require "atomy/method"
|
2
|
+
|
3
|
+
class Object
|
4
|
+
attr_reader :atomy_methods
|
5
|
+
|
6
|
+
def atomy_methods
|
7
|
+
@atomy_methods ||= {}
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module Atomy
|
12
|
+
module_function
|
13
|
+
|
14
|
+
def register_branch(target, name, branch)
|
15
|
+
methods = target.atomy_methods
|
16
|
+
method = methods[name] ||= Atomy::Method.new(name)
|
17
|
+
branch = method.add_branch(branch)
|
18
|
+
[method, branch]
|
19
|
+
end
|
20
|
+
|
21
|
+
def define_branch(binding, name, branch)
|
22
|
+
target =
|
23
|
+
if branch.receiver
|
24
|
+
branch.receiver.target
|
25
|
+
else
|
26
|
+
binding.constant_scope.for_method_definition
|
27
|
+
end
|
28
|
+
|
29
|
+
method, branch = register_branch(target, name, branch)
|
30
|
+
|
31
|
+
if branch.name
|
32
|
+
Rubinius.add_method(branch.name, branch.as_method, target, :public)
|
33
|
+
end
|
34
|
+
|
35
|
+
Rubinius.add_method(name, method.build, target, :public)
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,256 @@
|
|
1
|
+
require "atomy/grammar"
|
2
|
+
require "atomy/module"
|
3
|
+
require "atomy/code/assign"
|
4
|
+
require "atomy/code/block"
|
5
|
+
require "atomy/code/class_variable"
|
6
|
+
require "atomy/code/constant"
|
7
|
+
require "atomy/code/define_method"
|
8
|
+
require "atomy/code/define_function"
|
9
|
+
require "atomy/code/false"
|
10
|
+
require "atomy/code/instance_variable"
|
11
|
+
require "atomy/code/integer"
|
12
|
+
require "atomy/code/list"
|
13
|
+
require "atomy/code/nil"
|
14
|
+
require "atomy/code/pattern"
|
15
|
+
require "atomy/code/pattern/and"
|
16
|
+
require "atomy/code/pattern/quasi_quote"
|
17
|
+
require "atomy/code/pattern/splat"
|
18
|
+
require "atomy/code/pattern/wildcard"
|
19
|
+
require "atomy/code/quasi_quote"
|
20
|
+
require "atomy/code/quote"
|
21
|
+
require "atomy/code/self"
|
22
|
+
require "atomy/code/send"
|
23
|
+
require "atomy/code/sequence"
|
24
|
+
require "atomy/code/string_literal"
|
25
|
+
require "atomy/code/symbol"
|
26
|
+
require "atomy/code/true"
|
27
|
+
require "atomy/code/undefined"
|
28
|
+
require "atomy/code/variable"
|
29
|
+
require "atomy/node/meta"
|
30
|
+
require "atomy/node/equality"
|
31
|
+
require "atomy/pattern/and"
|
32
|
+
require "atomy/pattern/equality"
|
33
|
+
require "atomy/pattern/kind_of"
|
34
|
+
require "atomy/pattern/quasi_quote"
|
35
|
+
require "atomy/pattern/splat"
|
36
|
+
require "atomy/pattern/wildcard"
|
37
|
+
require "atomy/message_structure"
|
38
|
+
|
39
|
+
module Atomy
|
40
|
+
Bootstrap = Atomy::Module.new do
|
41
|
+
def expand(node)
|
42
|
+
node.accept(NodeExpander.new(self)) || super
|
43
|
+
end
|
44
|
+
|
45
|
+
def pattern(node)
|
46
|
+
node.accept(PatternExpander.new(self)) || super
|
47
|
+
end
|
48
|
+
|
49
|
+
def macro_definer(pattern, body)
|
50
|
+
BootstrapHelper::WithGrammar.new(Atomy::Code::DefineMethod.new(:expand, body, nil, [pattern]))
|
51
|
+
end
|
52
|
+
|
53
|
+
def pattern_definer(pattern, body)
|
54
|
+
BootstrapHelper::WithGrammar.new(Atomy::Code::DefineMethod.new(:pattern, body, nil, [pattern]))
|
55
|
+
end
|
56
|
+
|
57
|
+
def make_send(recv, msg, args = [])
|
58
|
+
Atomy::Code::Send.new(recv, msg.text, args)
|
59
|
+
end
|
60
|
+
|
61
|
+
def make_constant(name, parent = nil)
|
62
|
+
Atomy::Code::Constant.new(name, parent)
|
63
|
+
end
|
64
|
+
|
65
|
+
def make_sequence(nodes)
|
66
|
+
Atomy::Grammar::AST::Sequence.new(nodes)
|
67
|
+
end
|
68
|
+
|
69
|
+
def make_quasiquote(node)
|
70
|
+
Atomy::Grammar::AST::QuasiQuote.new(node)
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
class NodeExpander
|
76
|
+
def initialize(mod)
|
77
|
+
@module = mod
|
78
|
+
end
|
79
|
+
|
80
|
+
def visit(node)
|
81
|
+
structure = Atomy::MessageStructure.new(node)
|
82
|
+
|
83
|
+
block = nil
|
84
|
+
if block_arg = structure.block
|
85
|
+
block = Atomy::Code::Block.new(
|
86
|
+
Atomy::Code::Sequence.new(block_arg.body),
|
87
|
+
block_arg.arguments,
|
88
|
+
nil,
|
89
|
+
false,
|
90
|
+
)
|
91
|
+
end
|
92
|
+
|
93
|
+
Code::Send.new(
|
94
|
+
structure.receiver,
|
95
|
+
structure.name,
|
96
|
+
structure.arguments,
|
97
|
+
structure.splat_argument,
|
98
|
+
structure.proc_argument,
|
99
|
+
block,
|
100
|
+
)
|
101
|
+
rescue Atomy::MessageStructure::UnknownMessageStructure
|
102
|
+
end
|
103
|
+
|
104
|
+
def visit_stringliteral(node)
|
105
|
+
Code::StringLiteral.new(node.value)
|
106
|
+
end
|
107
|
+
|
108
|
+
def visit_sequence(node)
|
109
|
+
Code::Sequence.new(node.nodes)
|
110
|
+
end
|
111
|
+
|
112
|
+
def visit_list(node)
|
113
|
+
Code::List.new(node.nodes)
|
114
|
+
end
|
115
|
+
|
116
|
+
def visit_word(node)
|
117
|
+
case node.text
|
118
|
+
when :self
|
119
|
+
Code::Self.new
|
120
|
+
else
|
121
|
+
Code::Variable.new(node.text)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def visit_constant(node)
|
126
|
+
Code::Constant.new(node.text)
|
127
|
+
end
|
128
|
+
|
129
|
+
def visit_number(node)
|
130
|
+
Code::Integer.new(node.value)
|
131
|
+
end
|
132
|
+
|
133
|
+
def visit_quote(node)
|
134
|
+
Code::Quote.new(node.node)
|
135
|
+
end
|
136
|
+
|
137
|
+
def visit_quasiquote(node)
|
138
|
+
Code::QuasiQuote.new(node.node)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
class PatternExpander
|
143
|
+
def initialize(mod)
|
144
|
+
@module = mod
|
145
|
+
end
|
146
|
+
|
147
|
+
def visit(_)
|
148
|
+
nil
|
149
|
+
end
|
150
|
+
|
151
|
+
def visit_word(node)
|
152
|
+
name = nil
|
153
|
+
if node.text != :_
|
154
|
+
name = node.text
|
155
|
+
end
|
156
|
+
|
157
|
+
Code::Pattern::Wildcard.new(name)
|
158
|
+
end
|
159
|
+
|
160
|
+
def visit_number(node)
|
161
|
+
Code::Pattern.new(
|
162
|
+
Code::Send.new(
|
163
|
+
Code::Constant.new(
|
164
|
+
:Equality,
|
165
|
+
Code::Constant.new(
|
166
|
+
:Pattern,
|
167
|
+
Code::Constant.new(:Atomy))),
|
168
|
+
:new,
|
169
|
+
[node]))
|
170
|
+
end
|
171
|
+
|
172
|
+
def visit_quote(node)
|
173
|
+
Code::Pattern.new(
|
174
|
+
Code::Send.new(
|
175
|
+
Code::Constant.new(
|
176
|
+
:Equality,
|
177
|
+
Code::Constant.new(
|
178
|
+
:Pattern,
|
179
|
+
Code::Constant.new(:Atomy))),
|
180
|
+
:new,
|
181
|
+
[node]))
|
182
|
+
end
|
183
|
+
|
184
|
+
def visit_quasiquote(node)
|
185
|
+
Code::Pattern::QuasiQuote.new(node, @module)
|
186
|
+
end
|
187
|
+
|
188
|
+
def visit_prefix(node)
|
189
|
+
if node.operator == :*
|
190
|
+
Code::Pattern::Splat.new(@module.pattern(node.node))
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def visit_infix(node)
|
195
|
+
if node.operator == :&
|
196
|
+
Code::Pattern::And.new(@module.pattern(node.left), @module.pattern(node.right))
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def visit_constant(node)
|
201
|
+
Code::Pattern.new(
|
202
|
+
Code::Send.new(
|
203
|
+
Code::Constant.new(
|
204
|
+
:KindOf,
|
205
|
+
Code::Constant.new(
|
206
|
+
:Pattern,
|
207
|
+
Code::Constant.new(:Atomy))),
|
208
|
+
:new,
|
209
|
+
[node]))
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# helpers that shouldn't be exposed through using Bootstrap
|
215
|
+
module BootstrapHelper
|
216
|
+
extend self
|
217
|
+
|
218
|
+
class WithGrammar
|
219
|
+
def initialize(body)
|
220
|
+
@body = body
|
221
|
+
end
|
222
|
+
|
223
|
+
def bytecode(gen, mod)
|
224
|
+
gen.create_block(build_block(gen.state.scope, mod))
|
225
|
+
gen.send(:call, 0)
|
226
|
+
end
|
227
|
+
|
228
|
+
private
|
229
|
+
|
230
|
+
def build_block(scope, mod)
|
231
|
+
Atomy::Compiler.generate(mod.file) do |blk|
|
232
|
+
# close over the outer scope
|
233
|
+
blk.state.scope.parent = scope
|
234
|
+
|
235
|
+
# capture original module
|
236
|
+
blk.push_scope
|
237
|
+
blk.send(:module, 0)
|
238
|
+
|
239
|
+
# add Atomy::Grammar::AST to the constant scope
|
240
|
+
blk.push_cpath_top
|
241
|
+
blk.find_const(:Atomy)
|
242
|
+
blk.find_const(:Grammar)
|
243
|
+
blk.find_const(:AST)
|
244
|
+
blk.add_scope
|
245
|
+
|
246
|
+
# restore original module for definition targets
|
247
|
+
blk.push_scope
|
248
|
+
blk.swap
|
249
|
+
blk.send(:current_module=, 1)
|
250
|
+
|
251
|
+
mod.compile(blk, @body)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|