atomy 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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