atomy 0.1.1 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (172) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +13 -0
  3. data/LICENSE.md +201 -0
  4. data/bin/atomy +16 -133
  5. data/kernel/array.ay +6 -0
  6. data/kernel/atomy.ay +18 -0
  7. data/kernel/condition.ay +171 -271
  8. data/kernel/control-flow.ay +197 -192
  9. data/kernel/core.ay +120 -0
  10. data/kernel/data.ay +83 -39
  11. data/kernel/define.ay +84 -93
  12. data/kernel/doc.ay +282 -449
  13. data/kernel/dynamic.ay +25 -29
  14. data/kernel/file.ay +9 -0
  15. data/kernel/grammar.ay +267 -0
  16. data/kernel/hash.ay +17 -0
  17. data/kernel/interpolation.ay +59 -0
  18. data/kernel/io.ay +70 -244
  19. data/kernel/let-macro.ay +24 -0
  20. data/kernel/let-pattern.ay +24 -0
  21. data/kernel/loop.ay +80 -0
  22. data/kernel/mutation.ay +53 -0
  23. data/kernel/particles.ay +176 -39
  24. data/kernel/patterns.ay +527 -191
  25. data/kernel/pretty.ay +311 -277
  26. data/kernel/quotes.ay +29 -0
  27. data/kernel/range.ay +4 -0
  28. data/kernel/regexp.ay +23 -0
  29. data/kernel/repl.ay +83 -109
  30. data/kernel/stack-local.ay +21 -0
  31. data/lib/atomy.rb +37 -0
  32. data/lib/atomy/bootstrap.rb +256 -0
  33. data/lib/atomy/code/assign.rb +64 -0
  34. data/lib/atomy/code/block.rb +98 -0
  35. data/lib/atomy/code/class_variable.rb +17 -0
  36. data/lib/atomy/code/constant.rb +21 -0
  37. data/lib/atomy/code/define.rb +242 -0
  38. data/lib/atomy/code/define_function.rb +51 -0
  39. data/lib/atomy/code/define_method.rb +20 -0
  40. data/lib/atomy/code/false.rb +9 -0
  41. data/lib/atomy/code/instance_variable.rb +15 -0
  42. data/lib/atomy/code/integer.rb +13 -0
  43. data/lib/atomy/code/list.rb +17 -0
  44. data/lib/atomy/code/nil.rb +9 -0
  45. data/lib/atomy/code/pattern.rb +23 -0
  46. data/lib/atomy/code/pattern/and.rb +61 -0
  47. data/lib/atomy/code/pattern/quasi_quote.rb +185 -0
  48. data/lib/atomy/code/pattern/splat.rb +29 -0
  49. data/lib/atomy/code/pattern/wildcard.rb +37 -0
  50. data/lib/atomy/code/quasi_quote.rb +118 -0
  51. data/lib/atomy/code/quote.rb +13 -0
  52. data/lib/atomy/code/self.rb +9 -0
  53. data/lib/atomy/code/send.rb +110 -0
  54. data/lib/atomy/code/sequence.rb +23 -0
  55. data/lib/atomy/code/string_literal.rb +53 -0
  56. data/lib/atomy/code/symbol.rb +13 -0
  57. data/lib/atomy/code/true.rb +9 -0
  58. data/lib/atomy/code/undefined.rb +9 -0
  59. data/lib/atomy/code/variable.rb +17 -0
  60. data/lib/atomy/codeloader.rb +218 -0
  61. data/lib/atomy/compiler.rb +57 -0
  62. data/lib/atomy/errors.rb +54 -0
  63. data/lib/atomy/grammar.rb +2278 -0
  64. data/lib/atomy/locals.rb +75 -0
  65. data/lib/atomy/message_structure.rb +277 -0
  66. data/lib/atomy/method.rb +343 -0
  67. data/lib/atomy/module.rb +144 -0
  68. data/lib/atomy/node/constructable.rb +169 -0
  69. data/lib/atomy/node/equality.rb +113 -0
  70. data/lib/atomy/node/meta.rb +206 -0
  71. data/lib/atomy/node/pretty.rb +108 -0
  72. data/lib/atomy/parser.rb +21 -0
  73. data/lib/atomy/pattern.rb +26 -0
  74. data/lib/atomy/pattern/and.rb +59 -0
  75. data/lib/atomy/pattern/attribute.rb +16 -0
  76. data/lib/atomy/pattern/class_variable.rb +15 -0
  77. data/lib/atomy/pattern/equality.rb +42 -0
  78. data/lib/atomy/pattern/instance_variable.rb +15 -0
  79. data/lib/atomy/pattern/kind_of.rb +20 -0
  80. data/lib/atomy/pattern/or.rb +48 -0
  81. data/lib/atomy/pattern/quasi_quote.rb +164 -0
  82. data/lib/atomy/pattern/splat.rb +15 -0
  83. data/lib/atomy/pattern/wildcard.rb +18 -0
  84. data/lib/atomy/rubygems.rb +48 -0
  85. data/lib/atomy/version.rb +3 -0
  86. metadata +169 -134
  87. data/COPYING +0 -30
  88. data/README.md +0 -1
  89. data/kernel/block.ay +0 -30
  90. data/kernel/boot.ay +0 -10
  91. data/kernel/comparison.ay +0 -61
  92. data/kernel/concurrency.ay +0 -84
  93. data/kernel/cosmetics.ay +0 -3
  94. data/kernel/data-delta.ay +0 -105
  95. data/kernel/documentation.ay +0 -135
  96. data/kernel/errors.ay +0 -6
  97. data/kernel/format.ay +0 -13
  98. data/kernel/format/data.ay +0 -89
  99. data/kernel/format/formatter.ay +0 -345
  100. data/kernel/format/parser.ay +0 -13
  101. data/kernel/hashes.ay +0 -39
  102. data/kernel/namespaces.ay +0 -63
  103. data/kernel/node.ay +0 -48
  104. data/kernel/operators.ay +0 -28
  105. data/kernel/precision.ay +0 -148
  106. data/kernel/therie.ay +0 -204
  107. data/lib/ast/binary_send.rb +0 -44
  108. data/lib/ast/block.rb +0 -268
  109. data/lib/ast/constant.rb +0 -88
  110. data/lib/ast/internal/assign.rb +0 -19
  111. data/lib/ast/internal/block_pass.rb +0 -21
  112. data/lib/ast/internal/catch.rb +0 -247
  113. data/lib/ast/internal/class.rb +0 -30
  114. data/lib/ast/internal/class_variable.rb +0 -23
  115. data/lib/ast/internal/define.rb +0 -174
  116. data/lib/ast/internal/ensure.rb +0 -135
  117. data/lib/ast/internal/file.rb +0 -14
  118. data/lib/ast/internal/global_variable.rb +0 -20
  119. data/lib/ast/internal/if_then_else.rb +0 -24
  120. data/lib/ast/internal/instance_variable.rb +0 -17
  121. data/lib/ast/internal/let_macro.rb +0 -35
  122. data/lib/ast/internal/macro_quote.rb +0 -23
  123. data/lib/ast/internal/match.rb +0 -53
  124. data/lib/ast/internal/module.rb +0 -30
  125. data/lib/ast/internal/pattern.rb +0 -17
  126. data/lib/ast/internal/return.rb +0 -29
  127. data/lib/ast/internal/set.rb +0 -19
  128. data/lib/ast/internal/singleton_class.rb +0 -18
  129. data/lib/ast/internal/splat.rb +0 -14
  130. data/lib/ast/internal/when.rb +0 -24
  131. data/lib/ast/list.rb +0 -25
  132. data/lib/ast/macro.rb +0 -37
  133. data/lib/ast/node.rb +0 -599
  134. data/lib/ast/operator.rb +0 -21
  135. data/lib/ast/particle.rb +0 -13
  136. data/lib/ast/primitive.rb +0 -20
  137. data/lib/ast/quasi_quote.rb +0 -20
  138. data/lib/ast/quote.rb +0 -13
  139. data/lib/ast/send.rb +0 -104
  140. data/lib/ast/splice.rb +0 -32
  141. data/lib/ast/string.rb +0 -23
  142. data/lib/ast/unary.rb +0 -44
  143. data/lib/ast/unquote.rb +0 -45
  144. data/lib/ast/variable.rb +0 -64
  145. data/lib/atomy.kpeg.rb +0 -3995
  146. data/lib/code_loader.rb +0 -137
  147. data/lib/compiler/compiler.rb +0 -155
  148. data/lib/compiler/stages.rb +0 -81
  149. data/lib/formatter.kpeg.rb +0 -1394
  150. data/lib/macros.rb +0 -317
  151. data/lib/method.rb +0 -261
  152. data/lib/namespace.rb +0 -236
  153. data/lib/parser.rb +0 -28
  154. data/lib/patterns.rb +0 -276
  155. data/lib/patterns/any.rb +0 -21
  156. data/lib/patterns/attribute.rb +0 -59
  157. data/lib/patterns/block_pass.rb +0 -54
  158. data/lib/patterns/constant.rb +0 -33
  159. data/lib/patterns/default.rb +0 -44
  160. data/lib/patterns/head_tail.rb +0 -63
  161. data/lib/patterns/list.rb +0 -77
  162. data/lib/patterns/match.rb +0 -45
  163. data/lib/patterns/named.rb +0 -55
  164. data/lib/patterns/named_class.rb +0 -46
  165. data/lib/patterns/named_global.rb +0 -46
  166. data/lib/patterns/named_instance.rb +0 -46
  167. data/lib/patterns/particle.rb +0 -29
  168. data/lib/patterns/quasi_quote.rb +0 -184
  169. data/lib/patterns/quote.rb +0 -33
  170. data/lib/patterns/singleton_class.rb +0 -31
  171. data/lib/patterns/splat.rb +0 -57
  172. data/lib/util.rb +0 -37
@@ -0,0 +1,24 @@
1
+ use(require("core"))
2
+ use(require("define"))
3
+ use(require("patterns"))
4
+
5
+ require("atomy/bootstrap")
6
+
7
+ let-macro = class:
8
+ def(initialize(@body, @macros)) {}
9
+
10
+ def(bytecode(gen, mod)):
11
+ new = Atomy Module new: use(mod)
12
+
13
+ @macros each [`(~pat = ~exp)]:
14
+ definer = Atomy Bootstrap macro-definer(
15
+ Atomy Grammar AST QuasiQuote new(pat)
16
+ exp
17
+ )
18
+
19
+ new evaluate(definer, new compile-context)
20
+
21
+ new compile(gen, @body)
22
+
23
+ macro(let-macro(~*ms): ~*body):
24
+ let-macro new(`(do: ~*body), ms)
@@ -0,0 +1,24 @@
1
+ use(require("core"))
2
+ use(require("define"))
3
+ use(require("patterns"))
4
+
5
+ require("atomy/bootstrap")
6
+
7
+ let-pattern = class:
8
+ def(initialize(@body, @patterns)) {}
9
+
10
+ def(bytecode(gen, mod)):
11
+ new = Atomy Module new: use(mod)
12
+
13
+ @patterns each [`(~pat = ~exp)]:
14
+ definer = Atomy Bootstrap pattern-definer(
15
+ Atomy Grammar AST QuasiQuote new(pat)
16
+ exp
17
+ )
18
+
19
+ new evaluate(definer, new compile-context)
20
+
21
+ new compile(gen, @body)
22
+
23
+ macro(let-pattern(~*ms): ~*body):
24
+ let-pattern new(`(do: ~*body), ms)
data/kernel/loop.ay ADDED
@@ -0,0 +1,80 @@
1
+ use(require("core"))
2
+ use(require("define"))
3
+ use(require("dynamic"))
4
+ use(require("control-flow"))
5
+ use(require("patterns"))
6
+ use(require("let-macro"))
7
+ use(require("data"))
8
+ use(require("mutation"))
9
+
10
+ tags = dynamic(Hash new)
11
+
12
+ Atomy Grammar AST open:
13
+ data(GoTo(@name))
14
+
15
+ def(GoTo bytecode(gen, mod)):
16
+ gen goto(^tags fetch(@name))
17
+
18
+ labels = class:
19
+ def(initialize(@branches)) {}
20
+
21
+ def(bytecode(gen, mod)):
22
+ new-tags = Hash new
23
+
24
+ lbls = @branches collect [name, body]:
25
+ new-tags[name] = gen new-label
26
+
27
+ with(tags = new-tags):
28
+ lbls zip(@branches) each [l, [_, body]]:
29
+ l set!
30
+ mod compile(gen, body)
31
+ gen pop
32
+
33
+ gen push-nil
34
+
35
+
36
+ macro(labels: ~*branches):
37
+ branch-pairs = branches collect [`(~n: ~*body)]:
38
+ [n text, `(do: ~*body)]
39
+
40
+ `(let-macro(go(~'~name) = GoTo new(name text)):
41
+ ~(labels new(branch-pairs)))
42
+
43
+ macro(while(~test): ~*body):
44
+ `(labels:
45
+ loop:
46
+ unless(~test):
47
+ go(done)
48
+
49
+ let-macro(break = 'go(done),
50
+ next = 'go(loop)):
51
+ ~*body
52
+
53
+ go(loop)
54
+
55
+ done {})
56
+
57
+ macro(until(~test): ~*body):
58
+ `(labels:
59
+ loop:
60
+ when(~test):
61
+ go(done)
62
+
63
+ let-macro(break = 'go(done),
64
+ next = 'go(loop)):
65
+ ~*body
66
+
67
+ go(loop)
68
+
69
+ done {})
70
+
71
+ macro(loop: ~*body):
72
+ `(labels:
73
+ loop:
74
+ let-macro(break = 'go(done),
75
+ next = 'go(loop)):
76
+ ~*body
77
+
78
+ go(loop)
79
+
80
+ done {})
@@ -0,0 +1,53 @@
1
+ use(require("define"))
2
+ use(require("patterns"))
3
+ use(require("let-pattern"))
4
+ sl = require("stack-local")
5
+
6
+ -- variable mutation
7
+ let-pattern(Identifier = pattern(`(Word | (`(~Word)! | `(~Word)?)))):
8
+ macro(~(x & Identifier) += ~y): `(&~x = (~x + ~y))
9
+ macro(~(x & Identifier) -= ~y): `(&~x = (~x - ~y))
10
+ macro(~(x & Identifier) *= ~y): `(&~x = (~x * ~y))
11
+ macro(~(x & Identifier) **= ~y): `(&~x = (~x ** ~y))
12
+ macro(~(x & Identifier) /= ~y): `(&~x = (~x / ~y))
13
+ macro(~(x & Identifier) &= ~y): `(&~x = (~x & ~y))
14
+ macro(~(x & Identifier) |= ~y): `(&~x = (~x | ~y))
15
+
16
+ fn(attr-mutator(recv, attr, op, val)):
17
+ r = sl Local new
18
+ `(do:
19
+ ~(r set(recv))
20
+ ~r ~attr = ~(Atomy Grammar AST Infix new(`(~r ~attr), val, op)))
21
+
22
+ fn(index-mutator(recv, args, op, val)):
23
+ r = sl Local new
24
+ als = args collect [a]: sl Local new
25
+ `(do:
26
+ ~(r set(recv))
27
+ ~*(als zip(args) collect [[l, v]]: l set(v))
28
+ ~r[~*als] = ~(Atomy Grammar AST Infix new(`(~r[~*als]), val, op)))
29
+
30
+ macro(~r ~(x & Identifier) += ~y): attr-mutator(r, x, ."+", y)
31
+ macro(~r ~(x & Identifier) -= ~y): attr-mutator(r, x, ."-", y)
32
+ macro(~r ~(x & Identifier) *= ~y): attr-mutator(r, x, ."*", y)
33
+ macro(~r ~(x & Identifier) **= ~y): attr-mutator(r, x, ."**", y)
34
+ macro(~r ~(x & Identifier) /= ~y): attr-mutator(r, x, ."/", y)
35
+ macro(~r ~(x & Identifier) &= ~y): attr-mutator(r, x, ."&", y)
36
+ macro(~r ~(x & Identifier) |= ~y): attr-mutator(r, x, ."|", y)
37
+
38
+ macro(~r[~*x] += ~y): index-mutator(r, x, ."+", y)
39
+ macro(~r[~*x] -= ~y): index-mutator(r, x, ."-", y)
40
+ macro(~r[~*x] *= ~y): index-mutator(r, x, ."*", y)
41
+ macro(~r[~*x] **= ~y): index-mutator(r, x, ."**", y)
42
+ macro(~r[~*x] /= ~y): index-mutator(r, x, ."/", y)
43
+ macro(~r[~*x] &= ~y): index-mutator(r, x, ."&", y)
44
+ macro(~r[~*x] |= ~y): index-mutator(r, x, ."|", y)
45
+
46
+ -- other (ivar) mutation
47
+ macro(~x += ~y): `(~x = (~x + ~y))
48
+ macro(~x -= ~y): `(~x = (~x - ~y))
49
+ macro(~x *= ~y): `(~x = (~x * ~y))
50
+ macro(~x **= ~y): `(~x = (~x ** ~y))
51
+ macro(~x /= ~y): `(~x = (~x / ~y))
52
+ macro(~x &= ~y): `(~x = (~x & ~y))
53
+ macro(~x |= ~y): `(~x = (~x | ~y))
data/kernel/particles.ay CHANGED
@@ -1,53 +1,190 @@
1
- namespace(atomy)
1
+ use(require("core"))
2
+ use(require("define"))
3
+ use(require("data"))
4
+ use(require("control-flow"))
5
+ use(require("patterns"))
6
+ use(require("mutation"))
2
7
 
3
- for-macro:
4
- wildcard('_) := '_undefined
5
- wildcard(x) := x
8
+ data(Particle(@receiver, @message, @arguments))
6
9
 
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
- ])
10
+ def(Particle call(*args) &blk):
11
+ to-proc call(*args) &blk
15
12
 
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
- ])
13
+ Particle open:
14
+ alias-method(.[], .call)
24
15
 
25
- export:
26
- class(Particle < Array):
27
- call(*args) := to-proc [*args]
16
+ def(Particle to-proc):
17
+ [*args] &blk:
18
+ unless(args size >= arity):
19
+ raise(ArgumentError new((("given " + args size to-s) + ", expected ") + arity to-s))
28
20
 
29
- to-proc := [*args]:
30
- x = dup
21
+ [recv, cur] =
22
+ if(@receiver equal?(_))
23
+ then: [args[0], 1]
24
+ else: [@receiver, 0]
31
25
 
32
- args each [a]:
33
- idx = x find-index [a]:
34
- a equal?(_undefined)
26
+ filled =
27
+ @arguments collect [v]:
28
+ if(v equal?(_) && (args size >= cur))
29
+ then:
30
+ cur += 1
31
+ args[cur - 1]
32
+ else:
33
+ v
35
34
 
36
- when(idx):
37
- x [idx] = a
35
+ recv __send__(@message, *filled) &blk
38
36
 
39
- x first send(*(x drop(1)))
37
+ def(Particle arity):
38
+ required-args = 0
39
+ when(@receiver equal?(_)):
40
+ required-args += 1
40
41
 
41
- arity :=
42
- select(&#equal?(_undefined)) size
42
+ @arguments each [v]:
43
+ when(v equal?(_)):
44
+ required-args += 1
43
45
 
44
- receiver := at(0)
46
+ required-args
45
47
 
46
- message := at(1)
48
+ def(Particle == other):
49
+ other is-a?(self class) && (
50
+ (other receiver == @receiver) && (
51
+ (other message == @message) && (
52
+ other arguments == @arguments)))
47
53
 
48
- arguments := drop(2)
54
+ def(Symbol call(recv)): to-proc call(recv)
49
55
 
50
- class(Symbol):
51
- call(*args) := to-proc [*args]
56
+ def(Symbol arity): 1
52
57
 
53
- arity := 1
58
+ macro(.[~a, ~*as]):
59
+ `(Particle new(_, .[], [~a, ~*as]))
60
+
61
+ macro(.((~x)(~*as))):
62
+ `(Particle new(_, .~x, [~*as]))
63
+
64
+ macro(.(~r (~x)(~*as))):
65
+ `(Particle new(~r, .~x, [~*as]))
66
+
67
+ macro(.(~r [~*as])):
68
+ `(Particle new(~r, .[], [~*as]))
69
+
70
+ macro(.~(x & Infix)):
71
+ `(Particle new(
72
+ ~(x left || '_)
73
+ .~(StringLiteral new(x operator to-s))
74
+ [~(x right)]))
75
+
76
+ particle-klass = Particle
77
+
78
+ Atomy Pattern open:
79
+ self data(Particle(@receiver, @message, @arguments))
80
+
81
+ def(Particle target): particle-klass
82
+
83
+ def(Particle matches?(value)):
84
+ when(value is-a?(Symbol)):
85
+ &value = particle-klass new(_, value, [])
86
+
87
+ unless(value is-a?(particle-klass)):
88
+ return(false)
89
+
90
+ when(value message != @message):
91
+ return(false)
92
+
93
+ unless(@receiver matches?(value receiver)):
94
+ return(false)
95
+
96
+ @arguments matches?(value arguments)
97
+
98
+ def(Particle assign(scope, value)):
99
+ when(value is-a?(Symbol)):
100
+ &value = particle-klass new(_, value, [])
101
+
102
+ @receiver assign(scope, value receiver)
103
+ @arguments assign(scope, value arguments)
104
+
105
+ particle-pattern-code = Atomy Code Pattern class:
106
+ def(initialize(@receiver, @message, @arguments)) {}
107
+
108
+ def(bytecode(gen, mod)):
109
+ mod compile(gen, `(//Atomy Pattern Particle new(
110
+ ~@receiver
111
+ ~@message
112
+ ~@arguments
113
+ )))
114
+
115
+ def(assign(gen)):
116
+ assign-symbol = gen new-label
117
+ done = gen new-label
118
+
119
+ gen dup
120
+ gen push-cpath-top
121
+ gen find-const(.Symbol)
122
+ gen swap
123
+ gen kind-of
124
+ gen git(assign-symbol)
125
+
126
+ gen dup-many(2)
127
+ gen send(.receiver, 0)
128
+ gen swap
129
+ gen send(.receiver, 0)
130
+ gen swap
131
+ @receiver assign(gen)
132
+ gen pop-many(2)
133
+
134
+ gen dup-many(2)
135
+ gen send(.arguments, 0)
136
+ gen swap
137
+ gen send(.arguments, 0)
138
+ gen swap
139
+ @arguments assign(gen)
140
+ gen pop-many(2)
141
+
142
+ gen goto(done)
143
+
144
+ assign-symbol set!
145
+
146
+ gen dup-many(2)
147
+ gen pop
148
+ gen send(.receiver, 0)
149
+ gen push-undef
150
+ @receiver assign(gen)
151
+ gen pop-many(2)
152
+
153
+ gen dup-many(2)
154
+ gen pop
155
+ gen send(.arguments, 0)
156
+ gen make-array(0)
157
+ @arguments assign(gen)
158
+ gen pop-many(2)
159
+
160
+ done set!
161
+
162
+ pattern(.(~r [~*as])):
163
+ particle-pattern-code new(
164
+ pattern(r)
165
+ .[]
166
+ pattern(`[~*as]))
167
+
168
+ pattern(.[]):
169
+ Atomy Code Pattern new(`(Atomy Pattern Equality new(.[])))
170
+
171
+ pattern(.~(x & Word)):
172
+ Atomy Code Pattern new(`(Atomy Pattern Equality new(.~x)))
173
+
174
+ pattern(.(~(x & Word))!):
175
+ Atomy Code Pattern new(`(Atomy Pattern Equality new(.(~x)!)))
176
+
177
+ pattern(.(~(x & Word))?):
178
+ Atomy Code Pattern new(`(Atomy Pattern Equality new(.(~x)?)))
179
+
180
+ pattern(.[~a, ~*as]):
181
+ particle-pattern-code new(pattern('_), '.[], pattern(`[~a, ~*as]))
182
+
183
+ pattern(.~(x & Infix)):
184
+ particle-pattern-code new(pattern(x left || '_), `.~(StringLiteral new(x operator to-s)), pattern(`[~(x right)]))
185
+
186
+ pattern(.((~x)(~*as))):
187
+ particle-pattern-code new(pattern('_), `.~x, pattern(`[~*as]))
188
+
189
+ pattern(.(~r (~x)(~*as))):
190
+ particle-pattern-code new(pattern(r), `.~x, pattern(`[~*as]))
data/kernel/patterns.ay CHANGED
@@ -1,256 +1,592 @@
1
- namespace(atomy)
1
+ use(require("core"))
2
+ use(require("define"))
3
+ use(require("control-flow"))
2
4
 
3
- module(Atomy::Patterns):
4
- export:
5
- class(RuntimeClass < Pattern):
6
- initialize(@body, @name) := #ok
5
+ require("atomy/pattern/class_variable")
6
+ require("atomy/pattern/instance_variable")
7
+ require("atomy/pattern/attribute")
8
+ require("atomy/pattern/or")
7
9
 
8
- construct(g) := do:
9
- get(g)
10
- @body construct(g)
11
- @body compile(g)
12
- g send(#name, 0)
13
- g send(#new, 2)
10
+ instance-variable-pattern-code = Atomy Code Pattern class:
11
+ def(initialize(name)):
12
+ instance-variable-set("@name", name)
14
13
 
15
- (== b) :=
16
- b kind-of?(RuntimeClass) &&
17
- @body == b body &&
18
- @name == b name
14
+ def(bytecode(gen, mod)):
15
+ mod compile(gen, `(//Atomy Pattern Wildcard new))
19
16
 
20
- target(g) :=
21
- @body compile(g)
17
+ def(assign(gen)):
18
+ gen set-ivar(("@" + @name to-s) to-sym)
22
19
 
23
- matches?(g) := do:
24
- Atomy const-from-string(g, @name)
25
- g swap
26
- g kind-of
20
+ pattern(@~(name & Word)):
21
+ instance-variable-pattern-code new(name text)
27
22
 
28
- class(Predicate < Pattern):
29
- initialize(@pattern, @test) := #ok
23
+ pattern(@(~(name & Word))?):
24
+ instance-variable-pattern-code new((name text to-s + "?") to-sym)
30
25
 
31
- construct(g) := do:
32
- get(g)
33
- @pattern construct(g)
34
- @test construct(g)
35
- g send(#new, 2)
36
-
37
- (== b) :=
38
- b kind-of?(Predicate) &&
39
- @pattern == b pattern &&
40
- @test == b test
26
+ pattern(@(~(name & Word))!):
27
+ instance-variable-pattern-code new((name text to-s + "!") to-sym)
41
28
 
42
- target(g) := @pattern target(g)
29
+ kind-of-pattern-code = Atomy Code Pattern class:
30
+ def(initialize(@parent, @constant)) {}
43
31
 
44
- matches?(g) := do:
45
- mismatch = g new-label
46
- done = g new-label
32
+ def(bytecode(gen, mod)):
33
+ mod compile(gen, `(//Atomy Pattern KindOf new(~@parent ~@constant)))
47
34
 
48
- g dup
49
- @pattern matches?(g)
50
- g gif(mismatch)
35
+ pattern(~parent ~(constant & Constant)):
36
+ kind-of-pattern-code new(parent, constant)
51
37
 
52
- `{ ~@test } bytecode(g)
53
- g send(#block, 0)
54
- g swap
55
- g send(#call-on-instance, 1)
56
- g goto(done)
38
+ attribute-pattern-code = Atomy Code Pattern class:
39
+ def(initialize(@attribute, @receiver, @arguments)) {}
57
40
 
58
- mismatch set!
59
- g pop
60
- g push-false
41
+ def(bytecode(gen, mod)):
42
+ mod compile(gen, `(//Atomy Pattern Attribute new(~@receiver, [~*@arguments])))
61
43
 
62
- done set!
44
+ def(assign(gen)):
45
+ -- [value, pattern, value, pattern]
46
+ gen dup-many(2)
47
+ -- [pattern, value, value, pattern]
48
+ gen swap
49
+ -- [pattern, pattern, value, value, pattern]
50
+ gen dup
51
+ -- [receiver, pattern, value, value, pattern]
52
+ gen send(.receiver, 0)
53
+ -- [pattern, value, receiver, value, pattern]
54
+ gen move-down(2)
55
+ -- [[arguments], value, receiver, value, pattern]
56
+ gen send(.arguments, 0)
57
+ -- [<nil block>, [arguments], value, receiver, value, pattern]
58
+ gen push-nil
59
+ -- [assign result, value, pattern]
60
+ gen set-call-flags(2) -- CALL_FLAG_CONCAT
61
+ gen send-with-splat(((@attribute to-s) + "=") to-sym, 1)
62
+ -- [value, pattern]
63
+ gen pop
63
64
 
64
- deconstruct(g, locals = Hash new) :=
65
- @pattern deconstruct(g, locals)
65
+ pattern(~receiver ~(attribute & Word)):
66
+ attribute-pattern-code new(attribute text, receiver, [])
66
67
 
67
- local-names := @pattern local-names
68
+ pattern(~receiver (~(attribute & Word))?):
69
+ attribute-pattern-code new((attribute text to-s + "?") to-sym, receiver, [])
68
70
 
69
- bindings := @pattern bindings
71
+ pattern(~receiver (~(attribute & Word))!):
72
+ attribute-pattern-code new((attribute text to-s + "!") to-sym, receiver, [])
70
73
 
71
- class(With < Pattern):
72
- initialize(@expression, @pattern) := #ok
74
+ pattern(~receiver [~*arguments]):
75
+ attribute-pattern-code new("[]" to-sym, receiver, arguments)
73
76
 
74
- construct(g) := do:
75
- get(g)
76
- @expression construct(g)
77
- @pattern construct(g)
78
- g send(#new, 2)
77
+ class-variable-pattern-code = Atomy Code Pattern class:
78
+ def(initialize(@name)) {}
79
79
 
80
- (== b) :=
81
- b kind-of?(With) &&
82
- @expression == b expression &&
83
- @pattern == b pattern
80
+ def(bytecode(gen, mod)):
81
+ mod compile(gen, `(//Atomy Pattern Wildcard new))
84
82
 
85
- target(g) := Any new target(g)
83
+ def(assign(gen)):
84
+ gen dup
85
+ gen push-scope
86
+ gen swap
87
+ gen push-literal(("@@" + @name to-s) to-sym)
88
+ gen swap
89
+ gen send(.class-variable-set, 2)
90
+ gen pop
86
91
 
87
- matches?(g) := do:
88
- `{ ~@expression } bytecode(g)
89
- g send(#block, 0)
90
- g swap
91
- g send(#call-on-instance, 1)
92
- @pattern matches?(g)
93
92
 
94
- deconstruct(g, locals = Hash new) := do:
95
- `{ ~@expression } bytecode(g)
96
- g send(#block, 0)
97
- g swap
98
- g send(#call-on-instance, 1)
99
- @pattern deconstruct(g, locals)
93
+ pattern(@@~(name & Word)):
94
+ class-variable-pattern-code new(name text)
100
95
 
101
- local-names := @pattern local-names
96
+ pattern(@@(~(name & Word))?):
97
+ class-variable-pattern-code new((name text to-s + "?") to-sym)
102
98
 
103
- bindings := @pattern bindings
99
+ pattern(@@(~(name & Word))!):
100
+ class-variable-pattern-code new((name text to-s + "!") to-sym)
104
101
 
105
- class(And < Pattern):
106
- initialize(@a, @b) := #ok
102
+ pattern($~(name & Word)):
103
+ pattern(`(//Rubinius Globals[~(Atomy Code Symbol new(("$" + name text to-s) to-sym))]))
107
104
 
108
- construct(g) := do:
109
- get(g)
110
- @a construct(g)
111
- @b construct(g)
112
- g send(#new, 2)
105
+ pattern($(~(name & Word))?):
106
+ pattern(`(//Rubinius Globals[~(Atomy Code Symbol new(("$" + (name text to-s + "?")) to-sym))]))
113
107
 
114
- (== b) :=
115
- b kind-of?(And) &&
116
- @a == b a &&
117
- @b == b b
108
+ pattern($(~(name & Word))!):
109
+ pattern(`(//Rubinius Globals[~(Atomy Code Symbol new(("$" + (name text to-s + "!")) to-sym))]))
118
110
 
119
- target(g) :=
120
- @a target(g)
111
+ pattern(nil):
112
+ Atomy Code Pattern new(`(//Atomy Pattern Equality new(nil)))
121
113
 
122
- matches?(g) := do:
123
- mismatch = g new-label
124
- done = g new-label
114
+ pattern(true):
115
+ Atomy Code Pattern new(`(//Atomy Pattern Equality new(true)))
125
116
 
126
- g dup
127
- @a matches?(g)
128
- g gif(mismatch)
117
+ pattern(false):
118
+ Atomy Code Pattern new(`(//Atomy Pattern Equality new(false)))
129
119
 
130
- @b matches?(g)
131
- g dup
132
- g git(done)
120
+ pattern(~(x & StringLiteral)):
121
+ Atomy Code Pattern new(`(//Atomy Pattern Equality new(~x)))
133
122
 
134
- mismatch set!
135
- g pop
136
- g push-false
123
+ or-pattern-code = Atomy Code Pattern class:
124
+ def(initialize(@a, @b)) {}
137
125
 
138
- done set!
126
+ def(bytecode(gen, mod)):
127
+ mod compile(gen, `(//Atomy Pattern Or new(~@a, ~@b)))
139
128
 
140
- deconstruct(g, locals = Hash new) := do:
141
- g dup
142
- @a deconstruct(g, locals)
143
- @b deconstruct(g, locals)
129
+ def(assign(gen)):
130
+ done = gen new-label
131
+ assign-b = gen new-label
144
132
 
145
- local-names := [@a local-names + @b local-names] uniq
133
+ gen dup-many(2)
134
+ gen swap
135
+ gen send(.a, 0)
136
+ gen swap
137
+ gen send(.matches?, 1)
138
+ gen gif(assign-b)
146
139
 
147
- class(Or < Pattern):
148
- initialize(@a, @b) := #ok
140
+ gen dup-many(2)
141
+ gen swap
142
+ gen send(.a, 0)
143
+ gen swap
144
+ @a assign(gen)
145
+ gen pop-many(2)
149
146
 
150
- construct(g) := do:
151
- get(g)
152
- @a construct(g)
153
- @b construct(g)
154
- g send(#new, 2)
147
+ gen goto(done)
155
148
 
156
- (== b) :=
157
- b kind-of?(Or) &&
158
- @a == b a &&
159
- @b == b b
149
+ assign-b set!
160
150
 
161
- target(g) :=
162
- @a target(g)
151
+ gen dup-many(2)
152
+ gen swap
153
+ gen send(.b, 0)
154
+ gen swap
155
+ @b assign(gen)
156
+ gen pop-many(2)
163
157
 
164
- matches?(g) := do:
165
- matched = g new-label
166
- done = g new-label
158
+ done set!
167
159
 
168
- g dup
169
- @a matches?(g)
170
- g git(matched)
160
+ pattern(~a | ~b):
161
+ or-pattern-code new(pattern(a), pattern(b))
171
162
 
172
- @b matches?(g)
173
- g dup
174
- g gif(done)
163
+ Atomy Pattern open:
164
+ self class(With):
165
+ attr-reader(.block, .pattern)
175
166
 
176
- matched set!
177
- g pop
178
- g push-true
167
+ def(initialize(@block, @pattern)) {}
179
168
 
180
- done set!
169
+ def(matches?(val)):
170
+ @pattern matches?(@block call-on-object(val))
181
171
 
182
- deconstruct(g, locals = #[]) := do:
183
- b = g new-label
184
- done = g new-label
172
+ def(target):
173
+ Object
185
174
 
186
- g dup
187
- g dup
188
- @a matches?(g)
189
- g gif(b)
175
+ with-pattern-code = Atomy Code Pattern class:
176
+ def(initialize(@expr, @sub-pattern)) {}
190
177
 
191
- @a deconstruct(g, locals)
192
- g pop
193
- g goto(done)
178
+ def(bytecode(gen, mod)):
179
+ mod compile(gen, `(//Atomy Pattern With new({ ~@expr }, ~@sub-pattern)))
194
180
 
195
- b set!
196
- g pop
197
- @b deconstruct(g, locals)
181
+ def(assign(gen)):
182
+ -- [value, pattern, value, pattern]
183
+ gen dup-many(2)
198
184
 
199
- done set!
185
+ -- [pattern, value, value, pattern]
186
+ gen swap
200
187
 
201
- local-names := [@a local-names + @b local-names] uniq
188
+ -- [pattern, pattern, value, value, pattern]
189
+ gen dup
202
190
 
191
+ -- [with-block, pattern, value, value, pattern]
192
+ gen send(.block, 0)
203
193
 
204
- -- base patterns
205
- module(Atomy::AST):
206
- export:
207
- Variable pattern :=
208
- Atomy::Patterns::Named new $:
209
- @name
210
- Atomy::Patterns::Any new
194
+ -- [pattern, with-block, value, value, pattern]
195
+ gen swap
211
196
 
212
- Primitive pattern :=
213
- Atomy::Patterns::Match new(@value)
197
+ -- [with-pattern, with-block, value, value, pattern]
198
+ gen send(.pattern, 0)
214
199
 
215
- List pattern :=
216
- Atomy::Patterns::List new $:
217
- @elements collect [e]: e to-pattern
200
+ -- [with-block, value, with-pattern, value, pattern]
201
+ gen move-down(2)
218
202
 
219
- Constant pattern :=
220
- Atomy::Patterns::Constant new(self)
203
+ -- [value, with-block, with-pattern, value, pattern]
204
+ gen swap
221
205
 
222
- ScopedConstant pattern :=
223
- Atomy::Patterns::Constant new(self)
206
+ -- [block-result, with-pattern, value, pattern]
207
+ gen send(.call-on-object, 1)
224
208
 
225
- ToplevelConstant pattern :=
226
- Atomy::Patterns::Constant new(self)
209
+ -- [block-result, with-pattern, value, pattern]
210
+ @sub-pattern assign(gen)
227
211
 
228
- Quote pattern :=
229
- Atomy::Patterns::Quote new(@expression)
212
+ -- [value, pattern]
213
+ gen pop-many(2)
230
214
 
231
- Block pattern :=
232
- Atomy::Patterns::SingletonClass new(self)
215
+ pattern(with(~expr, ~pat)):
216
+ with-pattern-code new(expr, pattern(pat))
233
217
 
234
- Particle pattern :=
235
- Atomy::Patterns::Particle new(@name to-sym)
218
+ Atomy Pattern open:
219
+ self class(Predicate):
220
+ def(initialize(@block)) {}
236
221
 
237
- QuasiQuote pattern :=
238
- Atomy::Patterns::QuasiQuote new(self)
222
+ def(matches?(val)):
223
+ @block call-on-object(val)
239
224
 
240
- Send pattern :=
241
- if(@block)
242
- then:
243
- Atomy::Patterns::Named new $:
244
- @method-name
245
- @block contents [0] to-pattern
225
+ def(target):
226
+ Object
227
+
228
+ pattern({ ~*pred-body }):
229
+ Atomy Code Pattern new(`(//Atomy Pattern Predicate new({ ~*pred-body })))
230
+
231
+ Atomy Pattern open:
232
+ self class(List):
233
+ attr-reader(.patterns, .splat)
234
+
235
+ def(initialize(@patterns, @splat)) {}
236
+
237
+ def(matches?(val)):
238
+ unless(val is-a?(Array)):
239
+ return(false)
240
+
241
+ when(@splat && (val size < @patterns size)):
242
+ return(false)
243
+
244
+ when(!@splat && (val size != @patterns size)):
245
+ return(false)
246
+
247
+ idx = 0
248
+ mismatch = false
249
+ @patterns each [p]:
250
+ unless(p matches?(val[idx])):
251
+ &mismatch = true
252
+ -- TODO: break, or return false
253
+
254
+ &idx = (idx + 1)
255
+
256
+ if(mismatch)
257
+ then: false
246
258
  else:
247
- Atomy::Patterns::Attribute new $:
248
- @receiver
249
- @method-name
250
- @arguments
251
259
 
252
- String pattern :=
253
- Atomy::Patterns::Match new(@value)
260
+ if(@splat)
261
+ then: @splat matches?(val drop(idx))
262
+ else: true
263
+
264
+ def(assign(scope, val)):
265
+ idx = 0
266
+ @patterns each [p]:
267
+ p assign(scope, val[idx])
268
+ &idx = (idx + 1)
269
+
270
+ when(@splat):
271
+ @splat assign(scope, val drop(idx))
272
+
273
+ list-pattern-code = Atomy Code Pattern class:
274
+ def(initialize(patterns)):
275
+ @patterns = []
276
+ @splat = nil
277
+
278
+ patterns each [p]:
279
+ if(p splat?)
280
+ then: @splat = p
281
+ else: @patterns << p
282
+
283
+ def(bytecode(gen, mod)):
284
+ splat-node = (@splat || 'nil)
285
+ mod compile(gen, `(//Atomy Pattern List new([~*@patterns], ~splat-node)))
286
+
287
+ def(assign(gen)):
288
+ -- [[value], pattern, [value], pattern]
289
+ gen dup-many(2)
290
+
291
+ -- [pattern, [value], [value], pattern]
292
+ gen swap
293
+
294
+ -- [[pattern], [value], [value], pattern]
295
+ gen send(.patterns, 0)
296
+
297
+ @patterns each with-index [p, i]:
298
+ -- [pattern, [pattern], [value], [value], pattern]
299
+ gen shift-array
300
+
301
+ -- [[pattern], pattern, [value], [value], pattern]
302
+ gen swap
303
+
304
+ -- [[value], pattern, [pattern], [value], pattern]
305
+ gen rotate(3)
306
+
307
+ -- [value, [value], pattern, [pattern], [value], pattern]
308
+ gen shift-array
309
+
310
+ -- [[value], value, pattern, [pattern], [value], pattern]
311
+ gen swap
312
+
313
+ -- [value, pattern, [value], [pattern], [value], pattern]
314
+ gen move-down(2)
315
+
316
+ -- [value, pattern, [value], [pattern], [value], pattern]
317
+ p assign(gen)
318
+
319
+ -- [[value], [pattern], [value], pattern]
320
+ gen pop-many(2)
321
+
322
+ -- [[pattern], [value], [value], pattern]
323
+ gen swap
324
+
325
+ when(@splat):
326
+ -- [[remaining values], [value], pattern]
327
+ gen pop
328
+
329
+ -- [[value], [remaining values], pattern]
330
+ gen swap
331
+
332
+ -- [pattern, [remaining values], [value]]
333
+ gen rotate(3)
334
+
335
+ -- [pattern, pattern, [remaining values], [value]]
336
+ gen dup
337
+
338
+ -- [splat pattern, pattern, [remaining values], [value]]
339
+ gen send(.splat, 0)
340
+
341
+ -- [splatted pattern, pattern, [remaining values], [value]]
342
+ gen send(.pattern, 0)
343
+
344
+ -- [pattern, [remaining values], splatted pattern, [value]]
345
+ gen move-down(2)
346
+
347
+ -- [[remaining values], splatted pattern, [value], pattern]
348
+ gen move-down(3)
349
+
350
+ -- [[remaining values], splatted pattern, [value], pattern]
351
+ @splat assign(gen)
352
+
353
+ -- either pop the splatted values/pattern, or the two empty arrays if no splat
354
+ -- [[value], pattern]
355
+ gen pop-many(2)
356
+
357
+ -- list-pattern
358
+ pattern([~*pats]):
359
+ list-pattern-code new(pats collect [p]: pattern(p))
360
+
361
+ match = class:
362
+ def(initialize(@node, @branches)) {}
363
+
364
+ def(bytecode(gen, mod)):
365
+ gen create-block(build-block(gen state scope, mod))
366
+ mod compile(gen, @node)
367
+ gen send(.call, 1)
368
+
369
+
370
+ def(build-block(scope, mod)):
371
+ Atomy Compiler generate(mod file) [blk]:
372
+ -- close over the outer scope
373
+ blk state scope parent = scope
374
+
375
+ blk total-args = 1
376
+ blk required-args = 1
377
+ blk arity = 1
378
+
379
+ pairs = @branches collect [`(~pat: ~*body)]:
380
+ [mod pattern(pat), `(do: ~*body)]
381
+
382
+ -- create a local for the value being matched against
383
+ blk state scope new-local(."arg:match-value")
384
+
385
+ -- [node]
386
+ blk push-local(0)
387
+
388
+ done = blk new-label
389
+
390
+ pairs each [pat, body]:
391
+ skip = blk new-label
392
+
393
+ -- [pattern, node]
394
+ mod compile(blk, pat)
395
+
396
+ -- [pattern, node, pattern, node]
397
+ blk dup-many(2)
398
+
399
+ -- [node, pattern, pattern, node]
400
+ blk swap
401
+
402
+ -- [bool, pattern, node]
403
+ blk send(.matches?, 1)
404
+
405
+ -- [pattern, node]
406
+ blk gif(skip)
407
+
408
+ -- [node, pattern]
409
+ blk swap
410
+
411
+ -- [node, pattern]
412
+ pat assign(blk)
413
+
414
+ -- []
415
+ blk pop-many(2)
416
+
417
+ -- [value]
418
+ mod compile(blk, body)
419
+
420
+ -- [value]
421
+ blk goto(done)
422
+
423
+ -- [pattern, node]
424
+ skip set!
425
+
426
+ -- [node]
427
+ blk pop
428
+
429
+ -- []
430
+ blk pop
431
+
432
+ -- [value]
433
+ blk push-nil
434
+
435
+ -- [value]
436
+ done set!
437
+
438
+ def(assignment-local(gen, name)):
439
+ var = gen state scope search-local(name)
440
+
441
+ if(var && (var depth == 0))
442
+ then: [var, false]
443
+ else: [gen state scope new-local(name) nested-reference, true]
444
+
445
+
446
+ macro(~x match: ~*branches):
447
+ match new(x, branches)
448
+
449
+ rescue = class:
450
+ def(initialize(@node, @branches)) {}
451
+
452
+ -- TODO: this is pretty barebones compared to:
453
+ -- https://github.com/rubinius/rubinius-ast/blob/aa5ff6260a7647a9ef1035feb66b6d4b632d4211/lib/rubinius/ast/exceptions.rb
454
+ -- i'd rather prove out the complexity than blindly mirror it
455
+ def(bytecode(gen, mod)):
456
+ ok = gen new-label
457
+ ex = gen new-label
458
+ rescued = gen new-label
459
+
460
+ -- []
461
+ gen setup-unwind(ex, 0) -- RescueType
462
+
463
+ -- [value]
464
+ mod compile(gen, @node)
465
+
466
+ -- [value]
467
+ gen pop-unwind
468
+
469
+ -- [value]
470
+ gen goto(ok)
471
+
472
+ ex set!
473
+
474
+ -- []
475
+ -- gen pop
476
+
477
+ -- [exc_state]
478
+ gen push-exception-state
479
+
480
+ -- [block, exc_state]
481
+ gen create-block(build-block(gen state scope, mod))
482
+
483
+ -- [exc, block, exc_state]
484
+ gen push-current-exception
485
+
486
+ -- [value, exc_state]
487
+ gen send(.call, 1)
488
+
489
+ -- [value, value, exc_state]
490
+ gen dup
491
+
492
+ -- [value, exc_state]
493
+ gen goto-if-not-undefined(rescued)
494
+
495
+ -- [exc_state]
496
+ gen pop
497
+
498
+ -- []
499
+ gen restore-exception-state
500
+
501
+ -- []
502
+ gen reraise
503
+
504
+ -- [value, exc_state]
505
+ rescued set!
506
+
507
+ -- [exc_state, value]
508
+ gen swap
509
+
510
+ -- [value]
511
+ gen pop
512
+
513
+ -- [value]
514
+ ok set!
515
+
516
+ def(build-block(scope, mod)):
517
+ Atomy Compiler generate(mod file) [blk]:
518
+ -- close over the outer scope
519
+ blk state scope parent = scope
520
+
521
+ blk total-args = 1
522
+ blk required-args = 1
523
+ blk arity = 1
524
+
525
+ pairs = @branches collect [`(~pat: ~*body)]:
526
+ [mod pattern(pat), `(do: ~*body)]
527
+
528
+ -- create a local for the value being matched against
529
+ blk state scope new-local(."arg:match-value")
530
+
531
+ -- [node]
532
+ blk push-local(0)
533
+
534
+ done = blk new-label
535
+
536
+ pairs each [pat, body]:
537
+ skip = blk new-label
538
+
539
+ -- [pattern, node]
540
+ mod compile(blk, pat)
541
+
542
+ -- [pattern, node, pattern, node]
543
+ blk dup-many(2)
544
+
545
+ -- [node, pattern, pattern, node]
546
+ blk swap
547
+
548
+ -- [bool, pattern, node]
549
+ blk send(.matches?, 1)
550
+
551
+ -- [pattern, node]
552
+ blk gif(skip)
553
+
554
+ -- [node, pattern]
555
+ blk swap
556
+
557
+ -- [node, pattern]
558
+ pat assign(blk)
559
+
560
+ -- []
561
+ blk pop-many(2)
562
+
563
+ -- [value]
564
+ mod compile(blk, body)
565
+
566
+ -- [value]
567
+ blk goto(done)
568
+
569
+ -- [pattern, node]
570
+ skip set!
571
+
572
+ -- [node]
573
+ blk pop
574
+
575
+ -- []
576
+ blk pop
577
+
578
+ -- [value]
579
+ blk push-undef
580
+
581
+ -- [value]
582
+ done set!
583
+
584
+ def(assignment-local(gen, name)):
585
+ var = gen state scope search-local(name)
586
+
587
+ if(var && (var depth == 0))
588
+ then: [var, false]
589
+ else: [gen state scope new-local(name) nested-reference, true]
254
590
 
255
- Node pattern :=
256
- raise("unknown pattern: " + self inspect)
591
+ macro(~x rescue: ~*branches):
592
+ rescue new(x, branches)