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
@@ -0,0 +1,13 @@
1
+ namespace(atomy/format)
2
+
3
+ module(Atomy::Format):
4
+ require(File expand-path("../../../lib/formatter.kpeg.rb", _FILE))
5
+
6
+ class(Parser):
7
+ class(<< self):
8
+ parse(source) :=
9
+ new(source) onto:
10
+ unless(parse):
11
+ raise-error
12
+
13
+ result
data/kernel/hashes.ay ADDED
@@ -0,0 +1,39 @@
1
+ namespace(atomy)
2
+
3
+ macro(#(l: List)):
4
+ keys = []
5
+ values = []
6
+
7
+ l elements each [p]:
8
+ p match:
9
+ `(~k -> ~v) -> do:
10
+ keys << k
11
+ values << v
12
+
13
+ Atomy::AST::Send -> do:
14
+ while(p respond-to?(#block) && p block):
15
+ keys << Atomy::AST::Particle new(p line, p method-name)
16
+ values << p block contents first
17
+ p =! p receiver
18
+
19
+ Atomy::AST::Hash new(line, keys, values)
20
+
21
+ export:
22
+ class(Atomy::AST::Hash < Atomy::AST::Node):
23
+ children([#keys], [#values])
24
+ generate
25
+
26
+ bytecode(g) := do:
27
+ pos(g)
28
+
29
+ g push-cpath-top
30
+ g find-const(#Hash)
31
+ g push-int(@keys size)
32
+ g send(#new-from-literal, 1)
33
+
34
+ @keys each-with-index [n, i]:
35
+ g dup
36
+ n compile(g)
37
+ @values [i] compile(g)
38
+ g send("[]=" to-sym, 2)
39
+ g pop
data/kernel/io.ay ADDED
@@ -0,0 +1,244 @@
1
+ namespace(atomy)
2
+
3
+ -- condition kernel not loaded yet; predeclare this
4
+ symbols(error)
5
+
6
+ title"Input & Output"
7
+
8
+ doc"Where to write normal output." for:
9
+ dynamic(output-port, $stdout)
10
+
11
+ doc"Where to read input from." for:
12
+ dynamic(input-port, $stdin)
13
+
14
+ doc"Where to write error/warning output." for:
15
+ dynamic(error-port, $stderr)
16
+
17
+ section("Output"):
18
+ doc"
19
+ Write \hl{x to-s} to \hl{^output-port}, followed by a linebreak.
20
+ " spec {
21
+ => x
22
+ } for {
23
+ x print := x tap: ^output-port puts(x to-s)
24
+ } examples:
25
+ 1 print
26
+ "hello" print
27
+
28
+ doc"
29
+ Write \hl{x to-s} to \hl{^output-port}.
30
+ " spec {
31
+ => x
32
+ } for {
33
+ x display := x tap: ^output-port send(#print, x to-s)
34
+ } examples:
35
+ 1 display
36
+ "hello" display
37
+
38
+ doc"
39
+ Write \hl{x show} to \hl{^output-port}.
40
+ " spec {
41
+ => x
42
+ } for {
43
+ x write := x tap: ^output-port puts(x show)
44
+ } examples:
45
+ 1 write
46
+ "hello" write
47
+
48
+ doc"
49
+ Set \hl{^output-port} to write output to \hl{filename} for the duration \
50
+ of \hl{action}, ensuring that the file is closed.
51
+
52
+ Returns the result of \hl{action}.
53
+ " spec {
54
+ filename is-a?(String)
55
+ mode is-a?(String)
56
+ => any
57
+ } for {
58
+ with-output-to((filename: String), mode = "w", &action) :=
59
+ let(output-port = File open(filename, mode)):
60
+ action ensuring:
61
+ ^output-port close
62
+ } examples:
63
+ with-output-to("foo"):
64
+ 42 print
65
+
66
+ with-output-to("foo", "a"):
67
+ "hello" print
68
+
69
+ File open("foo", &#read)
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
@@ -0,0 +1,63 @@
1
+ macro(namespace(n: Variable)):
2
+ `(evaluate-when(compile, run, load):
3
+ Atomy::Namespace ensure(#~n))
4
+
5
+ macro(let-when(when, *bindings, &b)):
6
+ tmps = names(bindings size)
7
+ save = []
8
+ set = []
9
+ restore = []
10
+
11
+ bindings zip(tmps) [[`(~n = ~v), tmp]]:
12
+ save << `(Atomy::STATE [#~tmp] = ^~n)
13
+ set << set-dynvar(n, v)
14
+ restore << set-dynvar(n, `(Atomy::STATE delete(#~tmp)))
15
+
16
+ names [res]:
17
+ `(let(~*bindings):
18
+ evaluate-when(~when):
19
+ ~*save
20
+ ~*set
21
+
22
+ ~res = ~(b body)
23
+
24
+ evaluate-when(~when):
25
+ ~restore
26
+
27
+ ~res)
28
+
29
+ macro(in-namespace(n, &b)):
30
+ `(do:
31
+ evaluate-when(load):
32
+ Atomy::Namespace create(#~n)
33
+
34
+ let-when(compile, namespace = Atomy::Namespace ensure(#~n)):
35
+ ~(b body))
36
+
37
+ macro(no-namespace(&b)):
38
+ `(let-when(compile, namespace = nil):
39
+ ~(b body))
40
+
41
+ macro(export(&b)):
42
+ `(let-when(compile, define-in = "_"):
43
+ ~(b body))
44
+
45
+ macro(export-to(n, &b)):
46
+ `(let-when(compile, define-in = ~(n name)):
47
+ ~(b body))
48
+
49
+ macro(use(*ns)):
50
+ current = Atomy::Namespace get
51
+ where = current && current name
52
+
53
+ `(evaluate-when(compile, run, load):
54
+ ~*(ns collect [n]:
55
+ `(Atomy::Namespace get(~where) use(#~n))))
56
+
57
+ macro(symbols(*ns)):
58
+ current = Atomy::Namespace get
59
+ where = current && current name
60
+
61
+ `(evaluate-when(compile, run, load):
62
+ ~*(ns collect [n]:
63
+ `(Atomy::Namespace register(#~n, ~where))))
data/kernel/node.ay ADDED
@@ -0,0 +1,48 @@
1
+ namespace(atomy)
2
+
3
+ export:
4
+ module(Atomy::AST):
5
+ '_ pattern :=
6
+ Atomy::Patterns::Any new
7
+
8
+ `(~h . ~t) pattern :=
9
+ Atomy::Patterns::HeadTail new(h to-pattern, t to-pattern)
10
+
11
+ `(~p = ~d) pattern :=
12
+ Atomy::Patterns::Default new(p to-pattern, d)
13
+
14
+ `(? ~t) pattern :=
15
+ Atomy::Patterns::Predicate new(Atomy::Patterns::Any new, t)
16
+
17
+ `(~p ? ~t) pattern :=
18
+ Atomy::Patterns::Predicate new(p to-pattern, t)
19
+
20
+ `(~a & ~b) pattern :=
21
+ Atomy::Patterns::And new(a to-pattern, b to-pattern)
22
+
23
+ `(~a | ~b) pattern :=
24
+ Atomy::Patterns::Or new(a to-pattern, b to-pattern)
25
+
26
+ `(with(~attr, ~p)) pattern :=
27
+ Atomy::Patterns::With new(attr, p to-pattern)
28
+
29
+ `@@~n pattern :=
30
+ Atomy::Patterns::NamedClass new(n name)
31
+
32
+ `$~n pattern :=
33
+ Atomy::Patterns::NamedGlobal new(n name)
34
+
35
+ `@~n pattern :=
36
+ Atomy::Patterns::NamedInstance new(n name)
37
+
38
+ `%~x pattern :=
39
+ Atomy::Patterns::RuntimeClass new(x, nil)
40
+
41
+ `&~x pattern :=
42
+ Atomy::Patterns::BlockPass new(x to-pattern)
43
+
44
+ `*~x pattern :=
45
+ Atomy::Patterns::Splat new(x to-pattern)
46
+
47
+ `(Particle [~*as]) pattern :=
48
+ Atomy::Patterns::List new(as collect [a]: a to-pattern)
@@ -0,0 +1,28 @@
1
+ -- defining & assigning
2
+ operator right 0 = := **= *= <<= >>= &&=
3
+ &= ||= |= += -= /= ^= %=
4
+
5
+ -- association
6
+ operator right 1 <- ->
7
+
8
+ -- predicate pattern
9
+ operator right 2 ?
10
+
11
+ -- ranges
12
+ --operator 1 .. ...
13
+
14
+ -- comparison
15
+ operator 5 <=> < <= >= >
16
+ operator 4 == !=
17
+ operator 3 &&
18
+ operator 2 ||
19
+
20
+ -- math
21
+ operator right 12 **
22
+ operator 10 % * /
23
+ operator 9 + -
24
+
25
+ -- bitwise and shifting
26
+ operator 8 << >>
27
+ operator 6 ^ |
28
+ operator 7 &
@@ -0,0 +1,53 @@
1
+ namespace(atomy)
2
+
3
+ for-macro:
4
+ wildcard('_) := '_undefined
5
+ wildcard(x) := x
6
+
7
+ macro(#(x: Send)):
8
+ `(Particle [
9
+ ~(if(x private)
10
+ then: '_undefined
11
+ else: wildcard(x receiver))
12
+ ~(Atomy::AST::Particle new(0, x method-name))
13
+ ~*(x arguments collect [c]: wildcard(c))
14
+ ])
15
+
16
+ macro(#(x: BinarySend)):
17
+ `(Particle [
18
+ ~(if(x private)
19
+ then: '_undefined
20
+ else: wildcard(x lhs))
21
+ ~(Atomy::AST::Particle new(0, x operator))
22
+ ~(wildcard(x rhs))
23
+ ])
24
+
25
+ export:
26
+ class(Particle < Array):
27
+ call(*args) := to-proc [*args]
28
+
29
+ to-proc := [*args]:
30
+ x = dup
31
+
32
+ args each [a]:
33
+ idx = x find-index [a]:
34
+ a equal?(_undefined)
35
+
36
+ when(idx):
37
+ x [idx] = a
38
+
39
+ x first send(*(x drop(1)))
40
+
41
+ arity :=
42
+ select(&#equal?(_undefined)) size
43
+
44
+ receiver := at(0)
45
+
46
+ message := at(1)
47
+
48
+ arguments := drop(2)
49
+
50
+ class(Symbol):
51
+ call(*args) := to-proc [*args]
52
+
53
+ arity := 1