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
data/kernel/hashes.ay DELETED
@@ -1,39 +0,0 @@
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/namespaces.ay DELETED
@@ -1,63 +0,0 @@
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 DELETED
@@ -1,48 +0,0 @@
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)
data/kernel/operators.ay DELETED
@@ -1,28 +0,0 @@
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 &
data/kernel/precision.ay DELETED
@@ -1,148 +0,0 @@
1
- namespace(atomy)
2
-
3
- export:
4
- module(Atomy::Patterns):
5
- -- pattern precision hierarchy, from least precise to most
6
- [ [ Any, BlockPass, Splat, Attribute,
7
- NamedClass, NamedGlobal, NamedInstance
8
- ]
9
-
10
- [Constant, SingletonClass, RuntimeClass]
11
-
12
- [HeadTail]
13
-
14
- [List, QuasiQuote, Particle]
15
-
16
- [Match, Quote]
17
- ] each-with-index [ps, i]:
18
- ps each [a]:
19
- a send(#define-method, #precision):
20
- i
21
-
22
- Pattern precision := 0
23
-
24
- Named precision := @pattern precision
25
-
26
- Predicate precision :=
27
- @pattern precision + 1
28
-
29
- (a: Pattern) <=> (b: Pattern) :=
30
- a precision <=> b precision
31
-
32
- (a: BlockPass) <=> (b: BlockPass) :=
33
- a pattern <=> b pattern
34
-
35
- -- if one constant is a subclass of another, it is
36
- -- higher precision.
37
- (a: Constant) <=> (b: Constant) :=
38
- condition:
39
- (a ancestors nil? || b ancestors nil?) ->
40
- 0
41
-
42
- (a ancestors first == b ancestors first) ->
43
- 0
44
-
45
- b ancestors include?(a ancestors first) ->
46
- -1
47
-
48
- a ancestors include?(b ancestors first) ->
49
- 1
50
-
51
- otherwise ->
52
- 0
53
-
54
- (a: HeadTail) <=> (b: HeadTail) :=
55
- Atomy::Patterns
56
- compare([a head, a tail], [b head, b tail])
57
-
58
- (a: List) <=> (b: List) :=
59
- Atomy::Patterns
60
- compare(a patterns, b patterns)
61
-
62
- (a: Splat) <=> (b: Splat) :=
63
- a pattern <=> b pattern
64
-
65
- (a: Default) <=> (b: Default) :=
66
- a pattern <=> b pattern
67
- (d: Default) <=> (p: Pattern) := d pattern <=> p
68
- (p: Pattern) <=> (d: Default) := p <=> d pattern
69
-
70
- (a: Named) <=> (b: Named) :=
71
- a pattern <=> b pattern
72
- (n: Named) <=> (p: Pattern) :=
73
- n pattern <=> p
74
- (p: Pattern) <=> (n: Named) :=
75
- p <=> n pattern
76
-
77
-
78
- -- equivalence ignores named patterns
79
- (a: Named) =~ (b: Named) :=
80
- a pattern =~ b pattern
81
- Named =~ (p: Pattern) := pattern =~ p
82
- Pattern =~ (n: Named) := (=~ n pattern)
83
-
84
- Any =~ Any := true
85
-
86
- (a: BlockPass) =~ (b: BlockPass) :=
87
- a pattern =~ b pattern
88
-
89
- (a: Constant) =~ (b: Constant) :=
90
- a constant =~ b constant
91
-
92
- (a: Default) =~ (b: Default) :=
93
- a pattern =~ b pattern
94
- Default =~ (p: Pattern) := pattern =~ p
95
- Pattern =~ (n: Default) := (=~ n pattern)
96
-
97
- (a: HeadTail) =~ (b: HeadTail) :=
98
- a head =~ b head && a tail =~ b tail
99
-
100
- (a: List) =~ (b: List) :=
101
- a patterns zip(b patterns) all? [[a, b]]:
102
- when(a nil? || b nil?):
103
- return(false)
104
-
105
- a =~ b
106
-
107
- (a: Match) =~ (b: Match) :=
108
- a value == b value
109
-
110
- (a: SingletonClass) =~ (b: SingletonClass) :=
111
- a body == b body
112
-
113
- NamedClass =~ NamedClass := true
114
-
115
- NamedGlobal =~ NamedGlobal := true
116
-
117
- NamedInstance =~ NamedInstance := true
118
-
119
- (a: Particle) =~ (b: Particle) :=
120
- a value == b value
121
-
122
- (a: QuasiQuote) =~ (b: QuasiQuote) :=
123
- -- TODO: go through quotes.
124
- a expression == b expression
125
-
126
- (a: Quote) =~ (b: Quote) :=
127
- a expression == b expression
128
-
129
- (a: Splat) =~ (b: Splat) :=
130
- a pattern =~ b pattern
131
-
132
- (a: Attribute) =~ (b: Attribute) :=
133
- a receiver == b receiver &&
134
- a name == b name &&
135
- a arguments == b arguments
136
-
137
- Pattern =~ Pattern := false
138
-
139
-
140
- -- helper for comparing aggregate patterns like lists
141
- { self } compare(xs, ys) := do:
142
- total = 0
143
-
144
- xs zip(ys) [[x, y]]:
145
- unless(x nil? || y nil?):
146
- total += x <=> y
147
-
148
- total <=> 0
data/kernel/therie.ay DELETED
@@ -1,204 +0,0 @@
1
- namespace(therie)
2
-
3
- title"Testing with Therie"
4
-
5
- doc"
6
- Therie is a small and simple behavioral-style testing suite that comes with \
7
- Atomy. To use it, you should use the \hl{therie} namespace, which provides \
8
- the following methods.
9
-
10
- \atomy{
11
- use(therie)
12
- }
13
- "
14
-
15
- dynamic(nesting-level, 0)
16
-
17
- doc"
18
- A trivial container of \hl{passed} and \hl{failed} counts, with accessors \
19
- for both.
20
- " for:
21
- class(Stats):
22
- attr-accessor(#passed, #failed)
23
-
24
- export:
25
- initialize := do:
26
- @passed = 0
27
- @failed = 0
28
-
29
- inspect := f"Stats(@passed = %d, @failed = %d)" [@passed, @failed]
30
-
31
- dynamic(stats, nil)
32
-
33
-
34
- section("Structure"):
35
- doc"\evaluate{use(therie)}"
36
-
37
- doc"
38
- Run \hl{tests} and keep track of how many passed and how many failed, \
39
- printing the stats at the end and returning them.
40
- " spec {
41
- => Stats
42
- } for {
43
- theorize(&tests) :=
44
- let(stats = Stats new):
45
- tests call
46
- "\n" display
47
-
48
- ^stats onto:
49
- f"total of %d tests (%s passed, %s failed)" [
50
- failed + passed
51
- passed to-s colored(#green)
52
- if(failed == 0)
53
- then: "0"
54
- else: failed to-s colored(#red)
55
- ] display
56
-
57
- "\n" display
58
-
59
- ^stats
60
- } examples:
61
- theorize:
62
- describe("foo"):
63
- it("does x"): true should-be(false)
64
- it("does x"): true should-be(true)
65
-
66
-
67
- doc"
68
- Logically group together a set of behavior.
69
-
70
- Prints out \hl{what}, with each test in \hl{body} indented afterward.
71
- " for {
72
- describe(what, &body) := do:
73
- f"- %s" [what] indented print
74
-
75
- let(nesting-level = ^nesting-level + 1):
76
- body call
77
-
78
- nil
79
- } examples:
80
- describe("foo"):
81
- it("does x"): true should-be(false)
82
- it("does x"): true should-be(true)
83
-
84
-
85
- doc"
86
- Describe some behavior that the tests in \hl{body} will demonstrate.
87
- " for {
88
- it(description, &tests) := do:
89
- { tests call
90
- f"✓ %s" [description] indented colored(#green) print
91
- } rescue {
92
- e -> do:
93
- when(^stats):
94
- ^stats failed += 1
95
-
96
- f"✗ %s" [description] indented colored(#red) print
97
- f" ` %s: %s" [
98
- e class name
99
- e message
100
- ] indented colored(#yellow) print
101
-
102
- e backtrace first(5) each [l]:
103
- f" %s" [l colored(#cyan)] indented print
104
- } else:
105
- when(^stats):
106
- ^stats passed += 1
107
-
108
- nil
109
- } examples:
110
- it("adds correctly"): (2 + 2) should-be(4)
111
- it("adds correctly"): (1 + 2) should-be(4)
112
-
113
-
114
- section("Tests"):
115
- doc"\evaluate{use(therie)}"
116
-
117
- doc"
118
- Test that \hl{predicate} is satisified by \hl{o} by evaluating it with \
119
- \hl{o} as \hl{self}.
120
- " for {
121
- o should(&check) :=
122
- unless(o onto(&check)):
123
- raise(f"assertion failed for %v" [o])
124
- } examples:
125
- (2 + 2) should: even?
126
- (2 + 2) should: odd?
127
-
128
-
129
- doc"
130
- Test for \hl{x == y}.
131
- " for {
132
- x should-be(y) :=
133
- unless(x == y):
134
- raise(f"expected %v, got %v" [y, x])
135
- } examples:
136
- (2 + 2) should-be(4)
137
- (1 + 2) should-be(4)
138
-
139
-
140
- doc"
141
- Test that executing \hl{x} will raise an exception of class \hl{y}.
142
- " spec {
143
- x respond-to?(#call)
144
- y is-a?(Class)
145
- } for {
146
- x should-raise(y) :=
147
- x rescue {
148
- e ->
149
- unless(e kind-of?(y)):
150
- raise(f"expected exception %s, got: %s" [y, e])
151
- } else:
152
- raise("#should-raise - no exception raised")
153
- } examples:
154
- { abc } should-raise(NoMethodError)
155
- { #ok } should-raise(NoMethodError)
156
-
157
-
158
- doc"
159
- Test that executing \hl{x} will signal an error of class \hl{y}.
160
- " spec {
161
- x respond-to?(#call)
162
- y is-a?(Class)
163
- } for {
164
- x should-error(y) :=
165
- { with-restarts(errored -> nil):
166
- x call
167
- raise("#should-error - no error signaled")
168
- } bind {
169
- (e: ExceptionError) ->
170
- raise(e exception)
171
-
172
- (e: Error) -> do:
173
- when(e kind-of?(y)):
174
- restart(#errored)
175
-
176
- raise(f"expected error %s, got: %s" [y, e message])
177
- }
178
- } examples:
179
- { error(#foo) } should-error(SimpleError)
180
- { #ok } should-error(SimpleError)
181
-
182
-
183
- -- helpers
184
- String indented := " " * (^nesting-level * 2) + self
185
-
186
- String colored(color) := do:
187
- -- only makes sense to colorize if we're outputting to a terminal
188
- unless(^output-port tty?):
189
- return(self)
190
-
191
- codes =
192
- [ #black
193
- #red
194
- #green
195
- #yellow
196
- #blue
197
- #magenta
198
- #cyan
199
- #white
200
- ] zip((0 .. 7) to-a)
201
-
202
- hash = Hash [codes]
203
-
204
- "\e[9" + hash [color] to-s + "m" + self + "\e[0m"