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
data/COPYING ADDED
@@ -0,0 +1,30 @@
1
+ Copyright (c)2010, Alex Suraci
2
+
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ * Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+
11
+ * Redistributions in binary form must reproduce the above
12
+ copyright notice, this list of conditions and the following
13
+ disclaimer in the documentation and/or other materials provided
14
+ with the distribution.
15
+
16
+ * Neither the name of Alex Suraci nor the names of other
17
+ contributors may be used to endorse or promote products derived
18
+ from this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1 @@
1
+ Atomo-like language on the Rubinius VM.
data/bin/atomy ADDED
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env rbx
2
+
3
+ base = File.expand_path "../../lib/", __FILE__
4
+ kernel = File.expand_path "../../kernel/", __FILE__
5
+
6
+ require 'readline'
7
+ require 'optparse'
8
+
9
+ require base + "/macros"
10
+ require base + "/method"
11
+ require base + "/util"
12
+ require base + "/namespace"
13
+ require base + "/compiler/compiler"
14
+ require base + "/compiler/stages"
15
+ require base + "/parser"
16
+ require base + "/patterns"
17
+ require base + "/code_loader"
18
+
19
+ def require_atomy(*as)
20
+ before = Atomy::Namespace.get
21
+ begin
22
+ Atomy::CodeLoader.load_file *as
23
+ ensure
24
+ Atomy::Namespace.set(before)
25
+ end
26
+ end
27
+
28
+ options = {}
29
+
30
+ unless ARGV.empty? || ARGV[0][0] != ?-
31
+ OptionParser.new do |o|
32
+ o.banner = "usage: atomy [options]"
33
+
34
+ o.on("-B", "--print-bytecode", "print out compiled bytecode") do |v|
35
+ options[:debug] = v
36
+ end
37
+
38
+ o.on("-e", "--evaluate EXPR", "evaluate EXPR and print the result") do |v|
39
+ options[:evaluate] = v
40
+ end
41
+
42
+ o.on("-s", "--before-start EXPR", "evaluate EXPR beforehand") do |v|
43
+ options[:start] = v
44
+ end
45
+
46
+ o.on("-l", "--load FILE", "load FILENAME and start the REPL") do |v|
47
+ options[:load] = v
48
+ end
49
+
50
+ o.on("-d", "--documentation DIR", "generate documentation with output to DIR") do |v|
51
+ Atomy::CodeLoader.documentation = v
52
+ end
53
+
54
+ o.on_tail("-h", "--help", "show this message") do
55
+ puts o
56
+ exit
57
+ end
58
+ end.parse!
59
+ end
60
+
61
+ a = Time.now
62
+ puts "loading kernel"
63
+ require_atomy(kernel + "/boot.ay")
64
+ puts Time.now - a
65
+
66
+ Atomy::Namespace.ensure(:user)
67
+
68
+ def run_atomy(options)
69
+ if str = options[:evaluate] || options[:start]
70
+ $0 = "(eval)"
71
+ res = Atomy::Compiler.evaluate(
72
+ str,
73
+ nil,
74
+ "(eval)",
75
+ 1,
76
+ options[:debug]
77
+ )
78
+
79
+ if options[:evaluate]
80
+ res.send(Atomy.namespaced("atomy", "write").to_sym)
81
+ return
82
+ end
83
+ end
84
+
85
+ if file = options[:load] || ARGV[0]
86
+ $0 = file
87
+ require_atomy(file, ARGV[0] ? :run : :load, options[:debug])
88
+ return if ARGV[0]
89
+ end
90
+
91
+ if respond_to?(Atomy.namespaced("atomy", "repl").to_sym, true)
92
+ send(Atomy.namespaced("atomy", "repl").to_sym, File.expand_path("~/.atomy_history"))
93
+ else
94
+ $stderr.puts("main REPL startup failed! here's a basic one:")
95
+
96
+ history_file = File.expand_path("~/.atomy_history")
97
+
98
+ if File.exists?(history_file)
99
+ File.open(history_file, "r") do |f|
100
+ f.readlines.each do |l|
101
+ Readline::HISTORY << l.strip
102
+ end
103
+ end
104
+ end
105
+
106
+ begin
107
+ sane_history = []
108
+ while str = Readline.readline("> ")
109
+ next if str.empty?
110
+
111
+ sane_history << str
112
+
113
+ begin
114
+ res = Atomy::Compiler.evaluate str, TOPLEVEL_BINDING
115
+ if res.respond_to?(:pretty)
116
+ puts "=> #{res.pretty.render}"
117
+ else
118
+ puts "=> #{res.inspect}"
119
+ end
120
+ rescue StandardError => e
121
+ puts "ERROR!"
122
+ puts "#{e}:\n #{e.message}"
123
+ puts e.backtrace
124
+ end
125
+ end
126
+ ensure
127
+ File.open(history_file, "a") do |f|
128
+ f.puts(*sane_history)
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ run_atomy(options)
data/kernel/block.ay ADDED
@@ -0,0 +1,30 @@
1
+ namespace(atomy)
2
+
3
+ macro(x onto(&b)):
4
+ names [ctx]:
5
+ shadowed? = false
6
+
7
+ blk = b through-quotes [n]:
8
+ n match:
9
+ `@~(v: Atomy::AST::Variable) -> do:
10
+ shadowed? =! true
11
+ `(~ctx instance-variable-get(#~("@" + v name)))
12
+
13
+ 'self -> do:
14
+ shadowed? =! true
15
+ ctx
16
+
17
+ Atomy::AST::Send ? @private ->
18
+ n dup tap [p]:
19
+ p receiver = 'self
20
+
21
+ Atomy::AST::BinarySend ? @private ->
22
+ n dup tap [p]:
23
+ p lhs = 'self
24
+
25
+ _ ->
26
+ n
27
+
28
+ if(shadowed?)
29
+ then: `(do: ~ctx = self, ~blk block call-on-instance(~x))
30
+ else: `(~b block call-on-instance(~x))
data/kernel/boot.ay ADDED
@@ -0,0 +1,10 @@
1
+ macro(_LINE): line
2
+ macro(_FILE): Atomy::AST::File new(line)
3
+
4
+ macro(import(name)): `(require-atomy(~name, "load" to-sym))
5
+
6
+ "operators define cosmetics data comparison dynamic control-flow namespaces
7
+ patterns precision data-delta documentation particles hashes node block errors
8
+ doc pretty format concurrency io condition therie repl" split each [k]:
9
+ puts("loading " + k)
10
+ import(File expand-path("../", _FILE) + "/" + k)
@@ -0,0 +1,61 @@
1
+ module(Atomy::AST):
2
+ class(And < Node):
3
+ children(#a, #b)
4
+ generate
5
+
6
+ bytecode(g) := do:
7
+ pos(g)
8
+ done = g new-label
9
+ no = g new-label
10
+
11
+ @a compile(g)
12
+ g dup
13
+ g gif(done)
14
+
15
+ g pop
16
+ @b compile(g)
17
+
18
+ done set!
19
+
20
+ class(Or < Node):
21
+ children(#a, #b)
22
+ generate
23
+
24
+ bytecode(g) := do:
25
+ pos(g)
26
+ done = g new-label
27
+
28
+ @a compile(g)
29
+ g dup
30
+ g git(done)
31
+
32
+ g pop
33
+ @b compile(g)
34
+
35
+ done set!
36
+
37
+ class(Negate < Node):
38
+ children(#expression)
39
+ generate
40
+
41
+ bytecode(g) := do:
42
+ pos(g)
43
+ done = g new-label
44
+ yes = g new-label
45
+
46
+ @expression compile(g)
47
+ g git(yes)
48
+
49
+ g push-true
50
+ g goto(done)
51
+
52
+ yes set!
53
+ g push-false
54
+
55
+ done set!
56
+
57
+ macro(a && b): Atomy::AST::And new(line, a, b)
58
+ macro(a || b): Atomy::AST::Or new(line, a, b)
59
+ macro(!a): Atomy::AST::Negate new(line, a)
60
+ macro(a != b): `!(~a == ~b)
61
+ macro(a !~ b): `!(~a =~ ~b)
@@ -0,0 +1,84 @@
1
+ namespace(atomy)
2
+
3
+ require("actor")
4
+
5
+ title"Concurrency"
6
+
7
+ doc"
8
+ Get the current actor.
9
+ " spec {
10
+ => Actor
11
+ } for:
12
+ me := Actor current
13
+
14
+
15
+ section("Sending & Receiving"):
16
+ doc"
17
+ Send message \code{v} to the actor.
18
+ " spec {
19
+ => Actor
20
+ } for {
21
+ Actor <- v := send(v)
22
+ } examples:
23
+ a = spawn: receive { 42 -> #ok } write
24
+ a <- 42
25
+
26
+ doc"
27
+ Receive a message sent to the current actor that matches any of the \
28
+ patterns listed in \hl{body}. Blocks until a matching message is \
29
+ received. Non-matching messages are consumed and ignored.
30
+ " spec {
31
+ body contents all? [x]: x match { `(~_ -> ~_) -> true, _ -> false }
32
+ => any
33
+ } for {
34
+ macro(receive(&body)):
35
+ names [e]:
36
+ bs = body contents collect [`(~pat -> ~exp)]:
37
+ `(~e when('~pat to-pattern) [~pat]: ~exp)
38
+
39
+ `(Actor receive [~e]: ~*bs)
40
+ } examples:
41
+ a = spawn: receive { 1 -> #got-1 } write
42
+ a <- 0
43
+ a <- 2
44
+ a <- 1
45
+
46
+ doc"
47
+ Similar to \code{receive}, but with a timeout and an action to \
48
+ perform if it times out.
49
+ " spec {
50
+ body contents all? [x]: x match { `(~_ -> ~_) -> true, _ -> false }
51
+ timeout match: `(~_ -> ~_) -> true, _ -> false
52
+ => any
53
+ } for {
54
+ macro(receive(&body) after(timeout)):
55
+ names [e]:
56
+ bs = body contents collect [`(~pat -> ~exp)]:
57
+ `(~e when('~pat to-pattern) [~pat]: ~exp)
58
+
59
+ bs << `(~e after(~(timeout lhs)): ~(timeout rhs))
60
+
61
+ `(Actor receive [~e]: ~*bs)
62
+ } examples:
63
+ receive { 1 -> #ok } after(1 -> #too-slow)
64
+
65
+
66
+ section("Spawning"):
67
+ doc"
68
+ Spawn a new actor, performing \code{action}.
69
+ " spec {
70
+ => Actor
71
+ } for {
72
+ spawn(&action) := Actor send(#spawn, &action)
73
+ } examples:
74
+ spawn: (2 + 2) write
75
+
76
+ doc"
77
+ Spawn a new actor, performing \code{action}, linked to the current \
78
+ actor.
79
+ " spec {
80
+ => Actor
81
+ } for {
82
+ spawn-link(&action) := Actor send(#spawn-link, &action)
83
+ } examples:
84
+ spawn-link: (2 + 2) write
@@ -0,0 +1,277 @@
1
+ namespace(atomy)
2
+
3
+ title"Condition System"
4
+
5
+ doc"
6
+ Rather than traditional exceptions, Atomy sports a condition/restart \
7
+ system modeled on Common Lisp's design. The native Ruby exception handling \
8
+ is available, but conditions and restarts are much more flexible.
9
+ "
10
+
11
+ -- registered handlers/restarts
12
+ dynamic(handlers, [])
13
+ dynamic(restarts, [])
14
+
15
+ for-macro:
16
+ catcher(x) :=
17
+ Atomy::AST::Variable new(x line) $:
18
+ x match:
19
+ Atomy::AST::Variable ->
20
+ "restart:" + x name
21
+
22
+ Atomy::AST::Send ->
23
+ "restart:" + x method-name
24
+
25
+ data(Object):
26
+ Restart(@name, @action)
27
+
28
+ Restart invoke(*args) :=
29
+ throw(("restart:" + @name to-s) to-sym, @action [*args])
30
+
31
+ symbols(signal, warning, error, restart)
32
+
33
+ section("Conditions"):
34
+ doc"
35
+ Condition system hierarchy. You should subclass one of these to create \
36
+ your own conditions.
37
+ " for:
38
+ data(Object):
39
+ Condition:
40
+ Error(@backtrace):
41
+ SimpleError(@value)
42
+ ExceptionError(@exception)
43
+ NoRestartError(@name)
44
+ PortError(@port):
45
+ EndOfFile
46
+
47
+ Warning(@backtrace):
48
+ SimpleWarning(@value)
49
+
50
+ doc"
51
+ Get the name of a condition. By default, this will be the class name, \
52
+ but you may override this for your own behaviour.
53
+ " for:
54
+ Condition name := class name
55
+
56
+ ExceptionError name := @exception class name
57
+
58
+ doc"
59
+ A human-friendly message displayed for the condition. Override this.
60
+ " for:
61
+ Condition message := inspect
62
+
63
+ SimpleError message := @value to-s
64
+ ExceptionError message := @exception message
65
+ SimpleWarning message := @value to-s
66
+ NoRestartError message := "unknown restart " + @name show
67
+ EndOfFile message := "unexpected end-of-file for " + @port show
68
+
69
+
70
+ section("Handling"):
71
+ doc"
72
+ Invoke the \hl{name} restart, passing \hl{args} along to its callback.
73
+
74
+ See \hl{with-restarts}.
75
+ " spec {
76
+ name is-a?(Symbol)
77
+ => any
78
+ } for {
79
+ restart(name, *args) := do:
80
+ ^restarts each [r]:
81
+ when(r name == name):
82
+ r invoke(*args)
83
+
84
+ error(NoRestartError new(name))
85
+ } examples:
86
+ { with-restarts(foo -> 42):
87
+ signal(#bar)
88
+ } bind: #bar -> restart(#foo)
89
+
90
+
91
+ doc"
92
+ Register handlers for various signals for the duration of \hl{x}'s \
93
+ execution.
94
+
95
+ The body of \hl{y} is similar to \hl{match}; \hl{\italic{pattern} -> \
96
+ \italic{body}}.
97
+
98
+ The result is the result of \hl{body}.
99
+ " spec {
100
+ y contents all? [x]: x match { `(~_ -> ~_) -> true, _ -> false }
101
+ => any
102
+ } for {
103
+ macro(body bind(&y)):
104
+ names [a]:
105
+ callback = `([~a]: ~a match: ~*(y contents))
106
+ `(let(handlers = ^handlers + [~callback]):
107
+ ~body rescue:
108
+ (e: StandardError) -> error(e))
109
+ } examples:
110
+ { signal(#a) } bind: #a -> "got A!" print
111
+ { signal(#b) } bind: #a -> "got A!" print
112
+ { { signal(#a) } bind: #a -> "inner" print } bind: #a -> "outer" print
113
+
114
+
115
+ doc"
116
+ Register restarts available for the duration of \hl{body}'s execution.
117
+
118
+ The \hl{restarts} should be in the form of \
119
+ \hl{\italic{name}(*\italic{args}) -> \italic{body}}.
120
+
121
+ The result is the result of \hl{body}.
122
+ " spec {
123
+ => any
124
+ } for {
125
+ macro(with-restarts(*restarts, &block)):
126
+ rs = restarts collect [`(~n -> ~e)]:
127
+ n match:
128
+ Atomy::AST::Variable ->
129
+ `(Restart new(#~n, { ~e }))
130
+
131
+ Atomy::AST::Send -> do:
132
+ name = Atomy::AST::Variable new(0, n method-name)
133
+ `(Restart new(#~name, [~*(n arguments)] { ~e }))
134
+
135
+ body =
136
+ restarts reduce(
137
+ `{ ~block rescue: (e: StandardError) -> error(e) }
138
+ ) [x, `(~name -> ~_)]:
139
+ `{ catch(#~catcher(name), &~x) }
140
+
141
+ `(let(restarts = [~*rs] + ^restarts, &~body))
142
+ } examples:
143
+ { with-restarts(x -> 1, y -> 2):
144
+ signal(#a)
145
+ } bind: #a -> restart(#x)
146
+
147
+ { with-restarts(x -> 1, y -> 2):
148
+ signal(#a)
149
+ } bind: #a -> restart(#y)
150
+
151
+ { with-restarts(x(a) -> a * 7):
152
+ signal(#a)
153
+ } bind: #a -> restart(#x, 6)
154
+
155
+
156
+ section("Signalling"):
157
+ doc"
158
+ Signal a value through all bound handlers, nearest-first, stopping when \
159
+ a restart is invoked.
160
+ " spec {
161
+ => nil
162
+ } for {
163
+ signal(c) := do:
164
+ ^handlers reverse-each [callback]:
165
+ callback [c]
166
+
167
+ nil
168
+ } examples:
169
+ signal(#foo)
170
+ { signal(#foo) } bind: #foo -> "got foo" print
171
+
172
+
173
+ doc"
174
+ Like \hl{signal}, except that if no restart is invoked, the current \
175
+ \hl{^debugger} is started.
176
+
177
+ If the given value is not an \hl{Error}, it is wrapped in a \
178
+ \hl{SimpleError}. If the value is a Ruby \hl{Exception}, it is wrapped \
179
+ in an \hl{ExceptionError}.
180
+ " spec {
181
+ => _
182
+ } for {
183
+ error(x) := do:
184
+ e =
185
+ x match:
186
+ Exception ->
187
+ ExceptionError new(x) tap [err]:
188
+ err backtrace = x locations
189
+
190
+ Error ->
191
+ x tap [err]:
192
+ err backtrace = Rubinius::VM backtrace(0)
193
+
194
+ _ ->
195
+ SimpleError new(x) tap [err]:
196
+ err backtrace = Rubinius::VM backtrace(0)
197
+
198
+ signal(e)
199
+
200
+ with-output-to(^error-port):
201
+ ^debugger run(e)
202
+ } examples:
203
+ error("Oh no!")
204
+ { error("Oh no!") } bind: Error -> "INCOMING" print
205
+
206
+
207
+ doc"
208
+ Like \hl{signal}, except that if no restart is invoked, the warning is \
209
+ printed to \hl{^error-port}.
210
+
211
+ If the given value is not a \hl{Warning}, it is wrapped in a \
212
+ \hl{SimpleWarning}. Warning messages can be muffled by binding for \
213
+ \hl{Warning} and invoking the \hl{#muffle-warning} restart.
214
+ " spec {
215
+ => nil
216
+ } for {
217
+ warning(x) :=
218
+ with-restarts(muffle-warning -> nil):
219
+ w =
220
+ x match:
221
+ Warning ->
222
+ x tap [wrn]:
223
+ wrn backtrace = Rubinius::VM backtrace(0)
224
+
225
+ _ ->
226
+ SimpleWarning new(x) tap [wrn]:
227
+ wrn backtrace = Rubinius::VM backtrace(0)
228
+
229
+ signal(w)
230
+
231
+ with-output-to(^error-port):
232
+ (w name + ": " + w message) print
233
+
234
+ nil
235
+ } examples:
236
+ warning("Suspicious!")
237
+ { warning("Quiet, you!") } bind: Warning -> restart(#muffle-warning)
238
+
239
+
240
+ section("Debuggers"):
241
+ doc"
242
+ The default debugger. This will show the condition name, its message, \
243
+ and let the user pick from the available restarts.
244
+ " for:
245
+ class(DefaultDebugger):
246
+ class(<< self):
247
+ define(show-error-banner(e)):
248
+ ("-" * 78) print
249
+ (e name + ": " + e message) each-line [l]:
250
+ ("*** " + l) display
251
+
252
+ "\n" display
253
+
254
+ define(show-options-for(e)):
255
+ when(^restarts empty?):
256
+ exit(1)
257
+
258
+ "\n" display
259
+ "restarts:" print
260
+ ^restarts each-with-index [r, i]:
261
+ (" :" + i to-s + " -> " + r name to-s) print
262
+
263
+ define(run(e)):
264
+ show-error-banner(e)
265
+
266
+ show-options-for(e)
267
+
268
+ "!> " display
269
+ ^restarts [gets to-i] invoke
270
+
271
+ doc"
272
+ The current debugger. \hl{run} will be called with the condition as an \
273
+ argument.
274
+ " spec {
275
+ respond-to?(#run)
276
+ } for:
277
+ dynamic(debugger, DefaultDebugger)