forked from bakkdoor/fancy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
block.fy
207 lines (161 loc) · 4.49 KB
/
block.fy
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
class Block {
"""
The Block class (also BlockEnvironment) is the class of all
Block-literal values.
A Block is a piece of unevaluated code, that can be passed around as
any other value and evaluated by calling the +call+ or +call:+ methods.
Blocks also work properly with their enclosing environment in that
they preserve any local variables that get used within the Block,
even if the context in which they got defined has been destroyed.
=> Blocks are proper closures.
See: http://en.wikipedia.org/wiki/Closure_(computer_science) for
more information.
"""
def while_false: block {
"""
Executes a given @Block@ while self evals to @nil or @false.
Example:
i = 0
{ i >= 10 } while_false: {
i println
i = i + 1
}
"""
{ call not } while_true: block
}
alias_method: 'while_nil: for: 'while_false:
def while_true: block {
"""
@block @Block@ to call while @self yields @true.
Calls @block while calling @self yields a @true-ish value.
"""
try {
while_true_impl: block
} catch Fancy BreakIteration => b {
return b result
} catch Fancy StopIteration => s {
return s result
}
}
alias_method: 'while_do: for: 'while_true:
def until_do: block {
"""
@block @Block@ to be called while @self yields @nil or @false.
Calls a given Block as long as @self yields @nil or @false.
"""
self while_false: block
}
def until: block {
"""
@block Condition @Block@ to be called to determine if @self should be called.
Calls @self while @block yields @nil or @false.
"""
{ block call not } while_true: self
}
def && other_block {
"""
Short-circuiting && (boolean AND).
"""
if: call then: other_block else: {
return false
}
}
def || other_block {
"""
Short-circuiting || (boolean OR).
"""
call if_true: |val| {
return val
} else: other_block
}
def if: obj {
"""
@obj Condition object to determine if @self should be called.
Calls @self if @obj is true-ish.
"""
obj if_true: self
}
def unless: obj {
"""
@obj Condition object to determine if @self should not be called.
Opposite of Block#if:. Calls @self if @obj is false-ish.
"""
obj if_true: { nil } else: self
}
def === val {
"""
@val Other object to match @self against.
@return Value of calling @self with @val.
Matches a @Block against another object by calling @self with @val.
"""
call: [val]
}
def Block inspect {
name
}
def Block name {
"Block"
}
def [args] {
"""
Same as Block#call:
"""
call: args
}
def to_object {
"""
Creates and returns a new @Object@ with slots defined dynamically in @self.
Looks and feels similar to Javascript object literals.
Example:
o = {
something: \"foo bar baz\"
with: 42
} to_object
o something # => \"foo bar baz\"
o with # => 42
"""
obj = DynamicSlotObject new do: self . object
obj metaclass read_write_slots: (obj slots)
obj
}
def to_hash {
"""
Creates and returns a new @Hash@ with keys and values defined dynamically in @self.
Similar to @Block#object@ but returning a @Hash@ instead of an @Object@
Example:
o = {
something: \"foo bar baz\"
with: 42
} to_hash # => <['something => \"foo bar baz\", 'with => 42]>
"""
DynamicKeyHash new do: self . hash
}
def to_hash_deep {
"""
Creates and returns a new @Hash@ with keys and values defined dynamically in @self.
Similar to @Block#to_hash@ but converting any value that's a @Block@ to a @Hash@ as well.
Example:
o = {
something: \"foo bar baz\"
with: 42
and: {
another: 'field
}
} to_hash_deep # => <['something => \"foo bar baz\", 'with => 42, 'and => <['another => 'field]>]>
"""
DynamicKeyHash new: true . do: self . hash
}
def to_a {
"""
Creates and returns a new @Array@ with values defined dynamically in @self.
Similar to @Block#to_hash@ but returning an @Array@ instead of a @Hash@
Example:
a = {
something: \"foo bar baz\"
with: 42
something; else
} to_a # => [['something, \"foo bar baz\"], ['with, 42], 'something, 'else]
"""
DynamicValueArray new do: self . array
}
}