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/dynamic.ay
CHANGED
@@ -1,42 +1,38 @@
|
|
1
|
-
|
1
|
+
use(require("core"))
|
2
|
+
use(require("define"))
|
3
|
+
use(require("control-flow"))
|
4
|
+
use(require("data"))
|
5
|
+
use(require("hash"))
|
2
6
|
|
3
|
-
|
4
|
-
key(n) :=
|
5
|
-
Atomy::AST::Variable new $:
|
6
|
-
n line
|
7
|
-
"atomy_" + n resolve message-name
|
7
|
+
stack-local = require("stack-local")
|
8
8
|
|
9
|
-
|
10
|
-
`(Thread current [#~key(x)] || Atomy::DYNAMIC_ROOTS [#~x])
|
9
|
+
data(Dynvar(@default))
|
11
10
|
|
12
|
-
|
13
|
-
|
11
|
+
def(^Dynvar): values fetch(Thread current): @default
|
12
|
+
def(Dynvar get): values fetch(Thread current): _
|
13
|
+
def(Dynvar set(x)):
|
14
|
+
if(x == _)
|
15
|
+
then: values delete(Thread current)
|
16
|
+
else: values[Thread current] = x
|
14
17
|
|
15
|
-
|
16
|
-
|
18
|
+
-- TODO: this should be private
|
19
|
+
def(Dynvar values): @values = (@values || #{})
|
17
20
|
|
18
|
-
|
21
|
+
macro(dynamic): `dynamic(_)
|
22
|
+
macro(dynamic(~default)): `(Dynvar new(~default))
|
19
23
|
|
20
|
-
|
21
|
-
|
24
|
+
macro(with(~*bindings): ~*body):
|
25
|
+
tmps = bindings collect [b]: [b, stack-local Local new]
|
22
26
|
|
23
|
-
`(
|
27
|
+
save = tmps collect [`(~n = ~_), tmp]: tmp set(`(~n get))
|
24
28
|
|
25
|
-
|
29
|
+
set = bindings collect [`(~n = ~v)]: `(~n set(~v))
|
26
30
|
|
27
|
-
|
28
|
-
tmps = names(bindings size)
|
29
|
-
save = []
|
30
|
-
set = []
|
31
|
-
restore = []
|
32
|
-
|
33
|
-
bindings zip(tmps) [[`(~n = ~v), tmp]]:
|
34
|
-
save << `(~tmp = ~(dynvar(n)))
|
35
|
-
set << set-dynvar(n, v)
|
36
|
-
restore << set-dynvar(n, tmp)
|
31
|
+
restore = tmps collect [`(~n = ~_), tmp]: `(~n set(~tmp))
|
37
32
|
|
38
33
|
`(do:
|
39
34
|
~*save
|
40
|
-
{
|
41
|
-
|
35
|
+
do {
|
36
|
+
~*set
|
37
|
+
~*body
|
42
38
|
} ensuring: ~*restore)
|
data/kernel/file.ay
ADDED
data/kernel/grammar.ay
ADDED
@@ -0,0 +1,267 @@
|
|
1
|
+
use(require("core"))
|
2
|
+
use(require("define"))
|
3
|
+
use(require("control-flow"))
|
4
|
+
use(require("dynamic"))
|
5
|
+
use(require("particles"))
|
6
|
+
|
7
|
+
stack-local = require("stack-local")
|
8
|
+
|
9
|
+
require("kpeg")
|
10
|
+
require("kpeg/compiled_parser")
|
11
|
+
require("rubinius/processor") -- needed by compiler
|
12
|
+
require("rubinius/melbourne") -- needed by compiler
|
13
|
+
require("rubinius/compiler")
|
14
|
+
require("set")
|
15
|
+
|
16
|
+
|
17
|
+
-- lazily load these modules to prevent circular dependency
|
18
|
+
loaded-pretty = nil
|
19
|
+
fn(pretty): &loaded-pretty = (loaded-pretty || require("pretty"))
|
20
|
+
|
21
|
+
loaded-interpolation = nil
|
22
|
+
fn(intp): &loaded-interpolation = (loaded-interpolation || require("interpolation"))
|
23
|
+
|
24
|
+
|
25
|
+
actions = dynamic
|
26
|
+
setups = dynamic
|
27
|
+
vars = dynamic
|
28
|
+
rule = dynamic
|
29
|
+
rule-vars = dynamic
|
30
|
+
|
31
|
+
fn(const-name(c & Atomy Grammar AST Compose)): [const-name(c left), "::", const-name(c right)] join
|
32
|
+
fn(const-name(c & Atomy Grammar AST Constant)): c text to-s
|
33
|
+
|
34
|
+
fn(process-val(g, `(%(~grammar)(~name)(~*args)))):
|
35
|
+
`(~g foreign-invoke(
|
36
|
+
.~grammar
|
37
|
+
.~name
|
38
|
+
~(args collect &.(pretty show(_)) join(", "))))
|
39
|
+
|
40
|
+
fn(process-val(g, `(%(~grammar)(~name)))):
|
41
|
+
`(~g foreign-invoke(.~grammar, .~name))
|
42
|
+
|
43
|
+
fn(process-val(g, `((~name)=(~v)))):
|
44
|
+
val = process-val(g, v)
|
45
|
+
|
46
|
+
when(^rule-vars):
|
47
|
+
^rule-vars << name text
|
48
|
+
|
49
|
+
`(~g t(~val, ~(Atomy Grammar AST StringLiteral new(name text to-s))))
|
50
|
+
|
51
|
+
fn(process-val(g, `(~a ~b))):
|
52
|
+
`(~g seq(~process-val(g, a), ~process-val(g, b)))
|
53
|
+
|
54
|
+
fn(process-val(g, `(~a | ~b))):
|
55
|
+
process-val(g, `[~a, ~b])
|
56
|
+
|
57
|
+
fn(process-val(g, `[~*xs])):
|
58
|
+
original = ^rule-vars
|
59
|
+
new = Set new
|
60
|
+
choices =
|
61
|
+
xs collect [x]:
|
62
|
+
with(rule-vars = original dup):
|
63
|
+
choice = process-val(g, x)
|
64
|
+
new merge(^rule-vars - original)
|
65
|
+
choice
|
66
|
+
|
67
|
+
^rule-vars merge(new)
|
68
|
+
|
69
|
+
`(~g any(~*choices))
|
70
|
+
|
71
|
+
fn(process-val(g, a & `{ ~*bs })):
|
72
|
+
if(^actions)
|
73
|
+
then:
|
74
|
+
vars = ^rule-vars to-a
|
75
|
+
|
76
|
+
call = [
|
77
|
+
"actions["
|
78
|
+
^actions size to-s
|
79
|
+
"]["
|
80
|
+
vars collect &.to-s join(", ")
|
81
|
+
"]"
|
82
|
+
] join
|
83
|
+
|
84
|
+
^actions << [a, vars]
|
85
|
+
`(~g action(~(Atomy Grammar AST StringLiteral new(call))))
|
86
|
+
else:
|
87
|
+
`(~g action({ ~*bs }))
|
88
|
+
|
89
|
+
fn(process-val(g, `(<(~x)>))):
|
90
|
+
val = process-val(g, x)
|
91
|
+
|
92
|
+
when(^rule-vars):
|
93
|
+
^rule-vars << .text
|
94
|
+
|
95
|
+
`(~g collect(~val))
|
96
|
+
|
97
|
+
fn(process-val(g, `(@<(~x)>))):
|
98
|
+
`(~g bounds(~process-val(g, x)))
|
99
|
+
|
100
|
+
fn(process-val(g, `((~v)?))):
|
101
|
+
`(~g maybe(~process-val(g, v)))
|
102
|
+
|
103
|
+
fn(process-val(g, `((~v)+))):
|
104
|
+
`(~g many(~process-val(g, v)))
|
105
|
+
|
106
|
+
fn(process-val(g, `((~v)*))):
|
107
|
+
`(~g kleene(~process-val(g, v)))
|
108
|
+
|
109
|
+
fn(process-val(g, `&~v)):
|
110
|
+
`(~g andp(~process-val(g, v)))
|
111
|
+
|
112
|
+
fn(process-val(g, `!~v)):
|
113
|
+
`(~g notp(~process-val(g, v)))
|
114
|
+
|
115
|
+
fn(process-val(g, '_)):
|
116
|
+
`(~g dot)
|
117
|
+
|
118
|
+
fn(process-val(g, `(/(~(b & Atomy Grammar AST StringLiteral))/))):
|
119
|
+
if(^actions)
|
120
|
+
then:
|
121
|
+
vars = ^rule-vars to-a
|
122
|
+
|
123
|
+
-- this is a bit gross because it has to parse as a valid regexp
|
124
|
+
-- so we use .call() because actions[0][] is invalid
|
125
|
+
--
|
126
|
+
-- should be fine as the embedded parts are limited to numbers and words
|
127
|
+
call = [
|
128
|
+
"#{actions["
|
129
|
+
^actions size to-s
|
130
|
+
"].call("
|
131
|
+
vars collect &.to-s join(", ")
|
132
|
+
")}"
|
133
|
+
] join
|
134
|
+
|
135
|
+
^actions << [`{ ~(intp interpolated(b value)) }, vars]
|
136
|
+
|
137
|
+
`(~g reg(~(Atomy Grammar AST StringLiteral new(call))))
|
138
|
+
else:
|
139
|
+
`(~g reg(r~b))
|
140
|
+
|
141
|
+
fn(process-val(g, s & Atomy Grammar AST StringLiteral)):
|
142
|
+
`(~g str(~s))
|
143
|
+
|
144
|
+
fn(process-val(g, w & Atomy Grammar AST Word)):
|
145
|
+
`(~g ref(~(Atomy Grammar AST StringLiteral new(w text to-s))))
|
146
|
+
|
147
|
+
fn(process-val(g, `@~(w & Atomy Grammar AST Word))):
|
148
|
+
`(~g invoke(~(Atomy Grammar AST StringLiteral new(w text to-s))))
|
149
|
+
|
150
|
+
fn(process-val(g, `^~(w & Atomy Grammar AST Word))):
|
151
|
+
`(~g foreign-invoke("parent", ~(Atomy Grammar AST StringLiteral new(w text to-s))))
|
152
|
+
|
153
|
+
fn(process-val(g, c & Atomy Grammar AST Apply)):
|
154
|
+
args = [
|
155
|
+
"("
|
156
|
+
c arguments collect &.(pretty show(_)) join(", ")
|
157
|
+
")"
|
158
|
+
] join
|
159
|
+
|
160
|
+
`(~g ref(~(Atomy Grammar AST StringLiteral new(c node text to-s)), nil, ~(Atomy Grammar AST StringLiteral new(args))))
|
161
|
+
|
162
|
+
fn(process-val(g, `@~(c & Atomy Grammar AST Apply))):
|
163
|
+
args = [
|
164
|
+
"("
|
165
|
+
c arguments collect &.(pretty show(_)) join(", ")
|
166
|
+
")"
|
167
|
+
] join
|
168
|
+
|
169
|
+
`(~g invoke(~(Atomy Grammar AST StringLiteral new(c node text to-s)), ~(Atomy Grammar AST StringLiteral new(args))))
|
170
|
+
|
171
|
+
fn(process-val(g, `^~(c & Atomy Grammar AST Apply))):
|
172
|
+
args = [
|
173
|
+
"("
|
174
|
+
c arguments collect &.(pretty show(_)) join(", ")
|
175
|
+
")"
|
176
|
+
] join
|
177
|
+
|
178
|
+
`(~g foreign-invoke("parent", ~(Atomy Grammar AST StringLiteral new(c node text to-s)), ~(Atomy Grammar AST StringLiteral new(args))))
|
179
|
+
|
180
|
+
fn(process-val(_, s)):
|
181
|
+
raise(ArgumentError, "unknown parsing operator:\n" + s inspect)
|
182
|
+
|
183
|
+
parser-definer = class:
|
184
|
+
def(initialize(@source)) {}
|
185
|
+
|
186
|
+
def(bytecode(gen, mod)):
|
187
|
+
gen push-rubinius
|
188
|
+
gen push-literal(.__parser_init__)
|
189
|
+
gen push-literal(CodeTools Compiler compile-string(@source))
|
190
|
+
gen push-scope
|
191
|
+
gen push-self
|
192
|
+
gen send(.attach-method, 4)
|
193
|
+
gen pop
|
194
|
+
|
195
|
+
gen push-self
|
196
|
+
gen send(.__parser_init__, 0)
|
197
|
+
|
198
|
+
|
199
|
+
fn(process-toplevel(grammar, `%%{ ~*xs })):
|
200
|
+
call =
|
201
|
+
if(^setups)
|
202
|
+
then:
|
203
|
+
^setups << `{ ~*xs }
|
204
|
+
Atomy Grammar AST StringLiteral new(["setups[", (^setups size - 1) to-s, "][]"] join)
|
205
|
+
else:
|
206
|
+
`{ ~*xs }
|
207
|
+
|
208
|
+
`(~grammar add-setup(~grammar action(~call)))
|
209
|
+
|
210
|
+
fn(process-toplevel(grammar, `(%~name = ~const))):
|
211
|
+
`(~grammar add-foreign-grammar(
|
212
|
+
~(Atomy Grammar AST StringLiteral new(name text to-s))
|
213
|
+
~(Atomy Grammar AST StringLiteral new(const-name(const)))
|
214
|
+
))
|
215
|
+
|
216
|
+
fn(process-toplevel(grammar, `(rule((~name)(~*args)): ~val))):
|
217
|
+
with(rule = name text, rule-vars = //Set new(args collect &.text)):
|
218
|
+
`(~grammar set(
|
219
|
+
~(Atomy Grammar AST StringLiteral new(name text to-s))
|
220
|
+
~process-val(grammar, val)
|
221
|
+
[~*(args collect [x]: Atomy Grammar AST StringLiteral new(x text to-s))]
|
222
|
+
))
|
223
|
+
|
224
|
+
fn(process-toplevel(grammar, `(rule(~name): ~val))):
|
225
|
+
with(rule = name text, rule-vars = //Set new):
|
226
|
+
`(~grammar set(
|
227
|
+
~(Atomy Grammar AST StringLiteral new(name text to-s))
|
228
|
+
~process-val(grammar, val)
|
229
|
+
))
|
230
|
+
|
231
|
+
fn(process-toplevel(grammar, u)):
|
232
|
+
raise("unknown toplevel grammar form:\n" + u inspect)
|
233
|
+
|
234
|
+
macro(grammar: ~*body):
|
235
|
+
grammar = stack-local Local new
|
236
|
+
|
237
|
+
`(do:
|
238
|
+
~(grammar set(`(//KPeg Grammar new)))
|
239
|
+
~*(body collect [n]: process-toplevel(grammar, n))
|
240
|
+
~grammar)
|
241
|
+
|
242
|
+
|
243
|
+
macro(parser(~name): ~*grammar):
|
244
|
+
with(actions = [], setups = [], vars = []):
|
245
|
+
g = evaluate(`(grammar: ~*grammar))
|
246
|
+
|
247
|
+
acts =
|
248
|
+
^actions collect [action, as]:
|
249
|
+
args = as collect [a]: Word new(a)
|
250
|
+
`([~*args] ~action)
|
251
|
+
|
252
|
+
def = parser-definer new(//KPeg CodeGenerator new(const-name(name), g) output)
|
253
|
+
|
254
|
+
`(do:
|
255
|
+
//KPeg CompiledParser class(~name):
|
256
|
+
setups = [~*^setups]
|
257
|
+
vars = [~*^vars]
|
258
|
+
|
259
|
+
singleton:
|
260
|
+
def(setups): setups
|
261
|
+
def(vars): vars
|
262
|
+
|
263
|
+
def(actions): @actions ||= [~*acts]
|
264
|
+
|
265
|
+
~def
|
266
|
+
|
267
|
+
~name)
|
data/kernel/hash.ay
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
use(require("core"))
|
2
|
+
use(require("define"))
|
3
|
+
use(require("control-flow"))
|
4
|
+
use(require("patterns"))
|
5
|
+
|
6
|
+
stack-local = require("stack-local")
|
7
|
+
|
8
|
+
-- hash literals
|
9
|
+
macro(#{ ~*pairs }):
|
10
|
+
hash = stack-local Local new
|
11
|
+
|
12
|
+
init-hash = `(//Hash new-from-literal(~(Number new(pairs size))))
|
13
|
+
|
14
|
+
`(do:
|
15
|
+
~(hash set(init-hash))
|
16
|
+
~*(pairs collect [`(~k -> ~v)]: `(~hash [~k] = ~v))
|
17
|
+
~hash)
|
@@ -0,0 +1,59 @@
|
|
1
|
+
use(require("core"))
|
2
|
+
use(require("define"))
|
3
|
+
use(require("control-flow"))
|
4
|
+
use(require("quotes"))
|
5
|
+
use(require("range"))
|
6
|
+
use(require("grammar"))
|
7
|
+
use(require("patterns"))
|
8
|
+
|
9
|
+
parser(Parser):
|
10
|
+
%atomy = Atomy Grammar
|
11
|
+
|
12
|
+
rule(root): %atomy(wsp) es=(%atomy(expressions)) %atomy(wsp) "}" {
|
13
|
+
Atomy Grammar AST Sequence new(Array(es))
|
14
|
+
}
|
15
|
+
|
16
|
+
fn(intp-segments(s)):
|
17
|
+
s split(Regexp new("(?<!\\\\)#\\{"), 2) match:
|
18
|
+
[]: ['""]
|
19
|
+
|
20
|
+
[x]: [Atomy Code StringLiteral new(x, true)]
|
21
|
+
|
22
|
+
[pre, chunk]:
|
23
|
+
p = Parser new(chunk)
|
24
|
+
|
25
|
+
unless(p parse):
|
26
|
+
p raise-error
|
27
|
+
|
28
|
+
segments = [Atomy Code StringLiteral new(pre, true), `(~(p result) to-s)]
|
29
|
+
|
30
|
+
rest = p string[p pos .. -1]
|
31
|
+
|
32
|
+
if(rest nil? || rest empty?)
|
33
|
+
then: segments
|
34
|
+
else: segments + intp-segments(rest)
|
35
|
+
|
36
|
+
|
37
|
+
interpolation = class:
|
38
|
+
def(initialize(@segments)) {}
|
39
|
+
|
40
|
+
def(interpolated?): @segments size > 1
|
41
|
+
|
42
|
+
def(bytecode(gen, mod)):
|
43
|
+
@segments each [s]:
|
44
|
+
mod compile(gen, s)
|
45
|
+
|
46
|
+
when(interpolated?):
|
47
|
+
gen string-build(@segments size)
|
48
|
+
|
49
|
+
|
50
|
+
def(interpolated(x)): interpolation new(intp-segments(x))
|
51
|
+
|
52
|
+
macro-quoter(i) [_, _, v]: interpolated(v)
|
53
|
+
|
54
|
+
-- symbol literals with interpolation
|
55
|
+
macro(.~(x & StringLiteral)):
|
56
|
+
i = interpolated(x value)
|
57
|
+
if(i interpolated?)
|
58
|
+
then: `(~i to-sym)
|
59
|
+
else: Atomy Code Symbol new(x value to-sym)
|
data/kernel/io.ay
CHANGED
@@ -1,244 +1,70 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
doc"
|
72
|
-
Set \hl{^output-port} to write to \hl{io} for the duration of \hl{action}.
|
73
|
-
|
74
|
-
Returns the result of \hl{action}.
|
75
|
-
" spec {
|
76
|
-
=> any
|
77
|
-
} for {
|
78
|
-
with-output-to(io, &action) :=
|
79
|
-
let(output-port = io, &action)
|
80
|
-
} examples:
|
81
|
-
require("stringio")
|
82
|
-
x = StringIO new
|
83
|
-
with-output-to(x):
|
84
|
-
"hello!" write
|
85
|
-
x string
|
86
|
-
|
87
|
-
doc"
|
88
|
-
Set \hl{^error-port} to write error output to \hl{filename} for the \
|
89
|
-
duration of \hl{action}, ensuring that the file is closed.
|
90
|
-
|
91
|
-
Returns the result of \hl{action}.
|
92
|
-
" spec {
|
93
|
-
filename is-a?(String)
|
94
|
-
mode is-a?(String)
|
95
|
-
=> any
|
96
|
-
} for {
|
97
|
-
with-error-to((filename: String), mode = "w", &action) :=
|
98
|
-
let(error-port = File open(filename, mode)):
|
99
|
-
action ensuring:
|
100
|
-
^error-port close
|
101
|
-
} examples:
|
102
|
-
with-error-to("foo", "a"):
|
103
|
-
warning(#some-warning)
|
104
|
-
|
105
|
-
File open("foo", &#read)
|
106
|
-
|
107
|
-
doc"
|
108
|
-
Set \hl{^error-port} to write to \hl{io} for the duration of \hl{action}.
|
109
|
-
|
110
|
-
Returns the result of \hl{action}.
|
111
|
-
" spec {
|
112
|
-
=> any
|
113
|
-
} for {
|
114
|
-
with-error-to(io, &action) :=
|
115
|
-
let(error-port = io, &action)
|
116
|
-
} examples:
|
117
|
-
require("stringio")
|
118
|
-
x = StringIO new
|
119
|
-
|
120
|
-
with-error-to(x):
|
121
|
-
warning(#foo)
|
122
|
-
|
123
|
-
x string
|
124
|
-
|
125
|
-
section("Input"):
|
126
|
-
doc"
|
127
|
-
Read a line of text from \hl{^input-port}, signalling \hl{EndOfFile} on \
|
128
|
-
end of file. Lines are separated by \hl{sep}. A separator of \hl{nil} \
|
129
|
-
reads the entire contents, and a zero-length separator reads the input \
|
130
|
-
one paragraph at a time (separated by two linebreaks).
|
131
|
-
" spec {
|
132
|
-
=> String
|
133
|
-
} for {
|
134
|
-
read-line(sep = $separator) := do:
|
135
|
-
x = ^input-port gets(sep)
|
136
|
-
|
137
|
-
unless(x):
|
138
|
-
error(EndOfFile new(^input-port))
|
139
|
-
|
140
|
-
x
|
141
|
-
} examples:
|
142
|
-
with-input-from("foo"):
|
143
|
-
read-line
|
144
|
-
|
145
|
-
doc"
|
146
|
-
Read all lines of text from \hl{^input-port}. Lines are separated by \
|
147
|
-
\hl{sep}. A separator of \hl{nil} reads the entire contents as one \
|
148
|
-
segment, and a zero-length separator reads the input one paragraph at a \
|
149
|
-
time (separated by two linebreaks).
|
150
|
-
" spec {
|
151
|
-
=> String
|
152
|
-
} for {
|
153
|
-
read-lines(sep = $separator) := do:
|
154
|
-
x = ^input-port readlines(sep)
|
155
|
-
|
156
|
-
unless(x):
|
157
|
-
error(EndOfFile new(^input-port))
|
158
|
-
|
159
|
-
x
|
160
|
-
} examples:
|
161
|
-
with-input-from("foo"):
|
162
|
-
read-lines
|
163
|
-
|
164
|
-
doc"
|
165
|
-
Read a single byte from \hl{^input-port}, signalling \hl{EndOfFile} on \
|
166
|
-
end of file.
|
167
|
-
" spec {
|
168
|
-
=> Integer
|
169
|
-
} for {
|
170
|
-
read-byte := do:
|
171
|
-
x = ^input-port getc
|
172
|
-
|
173
|
-
unless(x):
|
174
|
-
error(EndOfFile new(^input-port))
|
175
|
-
|
176
|
-
x
|
177
|
-
} examples:
|
178
|
-
with-input-from("foo"):
|
179
|
-
read-byte
|
180
|
-
|
181
|
-
doc"
|
182
|
-
Same as \hl{read-byte chr}.
|
183
|
-
" spec {
|
184
|
-
=> String
|
185
|
-
} for {
|
186
|
-
read-char := read-byte chr
|
187
|
-
} examples:
|
188
|
-
with-input-from("foo"):
|
189
|
-
read-char
|
190
|
-
|
191
|
-
doc"
|
192
|
-
Read at most \hl{length} bytes from \hl{^input-port}, or to the end of \
|
193
|
-
file if \hl{length} is \hl{nil}. If \hl{buffer} is given, the data read \
|
194
|
-
will be written to it.
|
195
|
-
" spec {
|
196
|
-
length nil? || length >= 0
|
197
|
-
buffer nil? || buffer is-a?(String)
|
198
|
-
=> String || buffer || nil
|
199
|
-
} for {
|
200
|
-
read(length = nil, buffer = nil) :=
|
201
|
-
^input-port send(#read, length, buffer)
|
202
|
-
} examples:
|
203
|
-
x = ""
|
204
|
-
with-input-from("foo"):
|
205
|
-
read(10)
|
206
|
-
|
207
|
-
with-input-from("foo"):
|
208
|
-
read(10, x)
|
209
|
-
|
210
|
-
x
|
211
|
-
|
212
|
-
doc"
|
213
|
-
Set \hl{^input-port} to read input from \hl{filename} for the duration \
|
214
|
-
of \hl{action}, ensuring that the file is closed.
|
215
|
-
|
216
|
-
Returns the result of \hl{action}.
|
217
|
-
" spec {
|
218
|
-
filename is-a?(String)
|
219
|
-
mode is-a?(String)
|
220
|
-
=> any
|
221
|
-
} for {
|
222
|
-
with-input-from((filename: String), mode = "r", &action) :=
|
223
|
-
let(input-port = File open(filename, mode)):
|
224
|
-
action ensuring:
|
225
|
-
^input-port close
|
226
|
-
} examples:
|
227
|
-
with-input-from("foo"):
|
228
|
-
read-line
|
229
|
-
|
230
|
-
doc"
|
231
|
-
Set \hl{^input-port} to write to \hl{io} for the duration of \hl{action}.
|
232
|
-
|
233
|
-
Returns the result of \hl{action}.
|
234
|
-
" spec {
|
235
|
-
=> any
|
236
|
-
} for {
|
237
|
-
with-input-from(io, &action) :=
|
238
|
-
let(input-port = io, &action)
|
239
|
-
} examples:
|
240
|
-
require("stringio")
|
241
|
-
x = StringIO new("hello\ngoodbye\n")
|
242
|
-
|
243
|
-
with-input-from(x):
|
244
|
-
read-line
|
1
|
+
use(require("core"))
|
2
|
+
use(require("define"))
|
3
|
+
use(require("control-flow"))
|
4
|
+
|
5
|
+
use(require("dynamic"))
|
6
|
+
|
7
|
+
const-set(.OutputPort, dynamic(STDOUT))
|
8
|
+
const-set(.InputPort, dynamic(STDIN))
|
9
|
+
const-set(.ErrorPort, dynamic(STDERR))
|
10
|
+
|
11
|
+
def(puts(x)): x tap: ^OutputPort puts(x)
|
12
|
+
def(print(x)): x tap: ^OutputPort print(x)
|
13
|
+
|
14
|
+
def(with-output-to(filename & String, mode = "w") &action):
|
15
|
+
with(OutputPort = File open(filename, mode)):
|
16
|
+
action ensuring:
|
17
|
+
^OutputPort close
|
18
|
+
|
19
|
+
def(with-output-to(io) &action):
|
20
|
+
with(OutputPort = io):
|
21
|
+
action call
|
22
|
+
|
23
|
+
def(with-error-to(filename & String, mode = "w") &action):
|
24
|
+
with(ErrorPort = File open(filename, mode)):
|
25
|
+
action ensuring:
|
26
|
+
^ErrorPort close
|
27
|
+
|
28
|
+
def(with-error-to(io) &action):
|
29
|
+
with(ErrorPort = io):
|
30
|
+
action call
|
31
|
+
|
32
|
+
macro($separator): '(Rubinius Globals [."$/"])
|
33
|
+
|
34
|
+
def(read-line(sep = $separator)):
|
35
|
+
x = ^InputPort gets(sep)
|
36
|
+
|
37
|
+
unless(x):
|
38
|
+
error(EndOfFile new(^InputPort))
|
39
|
+
|
40
|
+
x
|
41
|
+
|
42
|
+
def(read-lines(sep = $separator)):
|
43
|
+
x = ^InputPort readlines(sep)
|
44
|
+
|
45
|
+
unless(x):
|
46
|
+
error(EndOfFile new(^InputPort))
|
47
|
+
|
48
|
+
x
|
49
|
+
|
50
|
+
def(read-byte):
|
51
|
+
x = ^InputPort getc
|
52
|
+
|
53
|
+
unless(x):
|
54
|
+
error(EndOfFile new(^InputPort))
|
55
|
+
|
56
|
+
x
|
57
|
+
|
58
|
+
def(read-char): read-byte chr
|
59
|
+
|
60
|
+
def(read(length = nil, buffer = nil)):
|
61
|
+
^InputPort read(length, buffer)
|
62
|
+
|
63
|
+
def(with-input-from(filename & String, mode = "r") &action):
|
64
|
+
with(InputPort = File open(filename, mode)):
|
65
|
+
action ensuring:
|
66
|
+
^InputPort close
|
67
|
+
|
68
|
+
def(with-input-from(io) &action):
|
69
|
+
with(InputPort = io):
|
70
|
+
action call
|