atomo programming language (fork of alex's atomo) — http://atomo-lang.org/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | Restart = Object clone
{ define: *handlers* as: []
define: *restarts* as: []
super do: {
Default-Debugger = Object clone do:
{ run: e :=
{ Restart show-options-for: e
"!> " display
Restart (get: read) jump: ()
} call
}
define: *debugger* as: Default-Debugger
define: *error-output* as: Port standard-error
Condition = Object clone
Error = Condition clone
Simple-Error = Error clone
Warning = Condition clone
Simple-Warning = Warning clone
}
(e: Simple-Error) describe-error := e value describe-error
(w: Simple-Warning) describe-error := w value describe-error
Simple-Error new: v :=
Simple-Error clone (delegating-to: v) do: { value = v }
Simple-Warning new: v :=
Simple-Warning clone (delegating-to: v) do: { value = v }
(e: Simple-Error) show := "<error " .. e value show .. ">"
(e: Simple-Warning) show := "<warning " .. e value show .. ">"
Restart show-options-for: e :=
{ { $- (repeat: 78) print
e describe-error
(word-wrap: 74)
lines
(map: { l | "*** " .. l })
unlines
print
halt when: *restarts* empty?
"restarts:" print
*restarts* (zip: (0 .. *restarts* length) (as: List)) map:
{ choice |
[index, name] = [choice to, choice from from]
(" :" .. index show .. " -> " .. name name) print
}
} call
} catch: { e |
"UH OH: error while showing error dialogue; dumping:\n " display
e dump
}
Restart get: (n: Integer) :=
*restarts* (at: n) to
Restart new: (a: Block) in: (c: Continuation) :=
{ res = *restarts*
Restart clone do:
{ jump: as := with: *restarts* as: res do: { c yield: (a call: as) }
action = a
context = c
}
} call
(r: -> Restart) show := "<restart " .. r action show .. ">"
macro (action with-restarts: (restarts: Block))
{ rs = restarts contents map:
{ `(~n -> ~e) |
e type match: {
@block -> `('~n -> ~e)
_ -> `('~n -> { ~e })
}
}
`(
{ cc action pairs |
restarts = pairs map:
{ a | a from -> (Restart new: a to in: cc) }
action with-restarts: restarts
} call/cc: (~action, ~(`List new: rs))
)
} call
macro (action with-restarts: (restarts: Block) bind: (handlers: Block))
`({ ~action with-restarts: ~restarts } bind: ~handlers)
(action: Block) with-restarts: (restarts: List) :=
modify: *restarts* as: { rs | restarts .. rs } do: action
(super) signal: v :=
{ *handlers* map: { h | h (call: v) (call: v) }
@ok
} call
(super) error: v := error: (Simple-Error new: v)
(super) error: (e: Error) :=
{ signal: e
with-output-to: *error-output* do: {
*debugger* run: e
}
} call
(super) warning: v := warning: (Simple-Warning new: v)
(super) warning: (w: Warning) :=
{ signal: w
with-output-to: *error-output* do: {
("WARNING: " .. w describe-error) print
}
@ok
} with-restarts: {
muffle-warning -> @ok
}
(super) restart: name := restart: name with: ()
(super) restart: name with: params :=
*restarts* (lookup: name) match: {
@(ok: r) ->
r jump: params
@none ->
error: @(unknown-restart: name)
}
(super) find-restart: name :=
*restarts* lookup: name
(super) with-handler: (h: Block) do: (action: Block) :=
modify: *handlers* as: { hs | h . hs } do: action
macro (a bind: (bs: Block))
{ branches = bs contents map:
{ `(~p -> ~e) |
if: (e type == @block)
then: { `(~p -> ~e) }
else: { `(~p -> { ~e }) }
}
handler = `Block new: (branches .. ['(_ -> { @ok })])
`({ h a |
with-handler: h do: a
} call: ({ !c | super = super; !c match: ~handler }, ~a))
} call
} call
|