mojombo-erlectricity 0.2.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/History.txt +14 -1
  2. data/LICENSE +20 -0
  3. data/README.md +130 -0
  4. data/Rakefile +63 -60
  5. data/VERSION.yml +4 -0
  6. data/examples/echo/README.md +12 -0
  7. data/examples/echo/echo.erl +13 -0
  8. data/examples/echo/echo.rb +11 -0
  9. data/examples/gruff/gruff.erl +17 -18
  10. data/examples/gruff/gruff_provider.rb +12 -19
  11. data/examples/gruff/{gruff_run.erl → gruff_run.sh} +5 -3
  12. data/examples/gruff/{stat_run.erl → stat_run.sh} +5 -3
  13. data/examples/gruff/stat_writer.erl +6 -6
  14. data/examples/simple/README.md +5 -0
  15. data/examples/simple/rerl.rb +111 -0
  16. data/examples/simple/rerl.sh +37 -0
  17. data/examples/tinderl/README.md +14 -0
  18. data/examples/tinderl/tinderl.erl +19 -21
  19. data/examples/tinderl/tinderl.rb +11 -10
  20. data/ext/decoder.c +67 -60
  21. data/lib/erlectricity/condition.rb +35 -20
  22. data/lib/erlectricity/conditions/boolean.rb +11 -0
  23. data/lib/erlectricity/conditions/hash.rb +9 -10
  24. data/lib/erlectricity/conditions/static.rb +31 -10
  25. data/lib/erlectricity/conditions/type.rb +14 -14
  26. data/lib/erlectricity/constants.rb +3 -4
  27. data/lib/erlectricity/decoder.rb +205 -199
  28. data/lib/erlectricity/encoder.rb +49 -35
  29. data/lib/erlectricity/errors/decode_error.rb +1 -1
  30. data/lib/erlectricity/errors/encode_error.rb +1 -1
  31. data/lib/erlectricity/errors/erlectricity_error.rb +1 -1
  32. data/lib/erlectricity/matcher.rb +15 -32
  33. data/lib/erlectricity/port.rb +11 -11
  34. data/lib/erlectricity/receiver.rb +54 -64
  35. data/lib/erlectricity/types/list.rb +3 -1
  36. data/lib/erlectricity.rb +4 -7
  37. data/test/condition_spec.rb +8 -9
  38. data/test/decode_spec.rb +27 -28
  39. data/test/encode_spec.rb +31 -24
  40. data/test/matcher_spec.rb +24 -12
  41. data/test/port_spec.rb +3 -4
  42. data/test/receiver_spec.rb +18 -20
  43. data/test/test_helper.rb +9 -5
  44. metadata +36 -29
  45. data/CONTRIBUTORS +0 -2
  46. data/Manifest.txt +0 -45
  47. data/README.txt +0 -43
  48. data/setup.rb +0 -1585
  49. data/test/test_erlectricity.rb +0 -2
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env escript
2
+ main(_) ->
3
+ Cmd = "ruby rerl.rb",
4
+ Port = open_port({spawn, Cmd}, [{packet, 4}, nouse_stdio, exit_status, binary]),
5
+ loop(Port).
6
+
7
+ send(Port, Message) ->
8
+ io:format("[erlang] sending: ~p~n", [Message]),
9
+ % can also use ! instead of port_command
10
+ % Port ! { self(), { command, term_to_binary(Message) } }.
11
+ port_command(Port, term_to_binary(Message)).
12
+
13
+ loop(Port) ->
14
+ receive
15
+ {Port, {data, In}} ->
16
+ Data = binary_to_term(In),
17
+ process(Port, Data);
18
+ Any ->
19
+ io:format("[erlang] other: ~p~n", [Any])
20
+ end,
21
+ loop(Port).
22
+
23
+ process(Port, i_am_alive) ->
24
+ io:format("[erlang] ruby is alive~n"),
25
+
26
+ send(Port, test),
27
+ send(Port, {atom, symbol}),
28
+ send(Port, {bool, true}),
29
+ send(Port, {number, 1}),
30
+ send(Port, {string, <<"reverse">>}),
31
+ send(Port, {array, [1,2,3]}),
32
+ send(Port, {array, [<<"abc">>, <<"cde">>]}),
33
+ send(Port, {hash, [{key,val}]}),
34
+ send(Port, {object, {1,{2},3,<<"four">>}});
35
+
36
+ process(Port, Data) ->
37
+ io:format("[erlang] received: ~p~n", [Data]).
@@ -0,0 +1,14 @@
1
+ This is a more advanced example of Erlectricity that shows how you can
2
+ integrate with Campfire via the Ruby "tinder" gem.
3
+
4
+ $ cd examples/tinderl
5
+ $ erl
6
+ Erlang (BEAM) emulator version 5.6.4 [source] [smp:2] [async-threads:0] [kernel-poll:false]
7
+
8
+ Eshell V5.6.4 (abort with ^G)
9
+ 1> c(tinderl).
10
+ {ok,tinderl}
11
+ 2> tinderl:start("example.campfireapp.com", "tom@example.com", "secret", "My Room").
12
+ <0.38.0>
13
+ 5> tinderl:speak("Hello, World!").
14
+ {speak,<0.31.0>,<<"Hello, World!">>}
@@ -1,17 +1,16 @@
1
1
  -module(tinderl).
2
2
  -export([start/4, stop/0, speak/1, paste/1]).
3
3
 
4
- start(Domain, Email, Password, Room) ->
5
- spawn(fun() ->
6
- register(tinderl, self()),
7
- process_flag(trap_exit, true),
4
+ start(Domain, Email, Password, Room) ->
5
+ spawn(fun() ->
6
+ register(tinderl, self()),
7
+ process_flag(trap_exit, true),
8
8
  Cmd = lists:flatten(io_lib:format("ruby ./tinderl.rb ~s ~s ~s ~s", [Domain, Email, Password, Room])),
9
- Port = open_port({spawn, Cmd}, [{packet, 4}, use_stdio, exit_status, binary]),
10
- port_loop(Port)
11
- end).
12
-
13
- stop() -> tinderl ! stop.
9
+ Port = open_port({spawn, Cmd}, [{packet, 4}, nouse_stdio, exit_status, binary]),
10
+ port_loop(Port)
11
+ end).
14
12
 
13
+ stop() -> tinderl ! stop.
15
14
 
16
15
  speak(String) when is_list(String) -> speak(list_to_binary(String));
17
16
  speak(String) when is_binary(String) -> tinderl ! {speak, self(), String}.
@@ -23,23 +22,22 @@ port_loop(Port) ->
23
22
  receive
24
23
  {speak, _Caller, String} ->
25
24
  Data = term_to_binary({speak, String}),
26
- Port ! {self(), {command, Data}},
25
+ Port ! {self(), {command, Data}},
27
26
 
28
27
  port_loop(Port);
29
-
28
+
30
29
  {paste, _Caller, String} ->
31
30
  Data = term_to_binary({paste, String}),
32
- Port ! {self(), {command, Data}},
31
+ Port ! {self(), {command, Data}},
33
32
 
34
33
  port_loop(Port);
35
-
36
- stop ->
37
- Port ! {self(), close},
38
- receive
39
- {Port, closed} -> exit(normal)
40
- end;
41
-
34
+
35
+ stop ->
36
+ Port ! {self(), close},
37
+ receive
38
+ {Port, closed} -> exit(normal)
39
+ end;
40
+
42
41
  {'EXIT', Port, Reason} ->
43
42
  exit({port_terminated,Reason})
44
- end.
45
-
43
+ end.
@@ -1,6 +1,7 @@
1
- $:.unshift(File.dirname(__FILE__) + "/../../lib/")
2
- require 'erlectricity'
1
+ $:.unshift File.join(File.dirname(__FILE__), *%w[../../lib])
2
+
3
3
  require 'rubygems'
4
+ require 'erlectricity'
4
5
  require 'tinder'
5
6
 
6
7
  domain, email, password, room_name = *ARGV
@@ -9,18 +10,18 @@ campfire.login email, password
9
10
  room = campfire.find_room_by_name room_name
10
11
 
11
12
  receive do |f|
12
- f.when(:speak, Any) do |comment|
13
- room.speak comment
13
+ f.when([:speak, Any]) do |comment|
14
+ room.speak(comment)
14
15
  f.receive_loop
15
- end
16
-
17
- f.when(:paste, Any) do |comment|
18
- room.paste comment
16
+ end
17
+
18
+ f.when([:paste, Any]) do |comment|
19
+ room.paste(comment)
19
20
  f.receive_loop
20
21
  end
21
-
22
+
22
23
  f.when(Any) do |obj|
23
- STDERR.write obj.inspect
24
+ p obj
24
25
  end
25
26
  end
26
27
 
data/ext/decoder.c CHANGED
@@ -25,7 +25,7 @@ static VALUE mErlectricity;
25
25
  static VALUE cDecoder;
26
26
  void Init_decoder();
27
27
 
28
- VALUE method_read_any_from(VALUE klass, VALUE rString);
28
+ VALUE method_decode(VALUE klass, VALUE rString);
29
29
 
30
30
  VALUE read_any_raw(unsigned char **pData);
31
31
 
@@ -79,16 +79,16 @@ VALUE read_small_tuple(unsigned char **pData) {
79
79
  if(read_1(pData) != ERL_SMALL_TUPLE) {
80
80
  rb_raise(rb_eStandardError, "Invalid Type, not a small tuple");
81
81
  }
82
-
82
+
83
83
  int arity = read_1(pData);
84
-
84
+
85
85
  VALUE array = rb_ary_new2(arity);
86
-
86
+
87
87
  int i;
88
88
  for(i = 0; i < arity; ++i) {
89
89
  rb_ary_store(array, i, read_any_raw(pData));
90
90
  }
91
-
91
+
92
92
  return array;
93
93
  }
94
94
 
@@ -96,16 +96,16 @@ VALUE read_large_tuple(unsigned char **pData) {
96
96
  if(read_1(pData) != ERL_LARGE_TUPLE) {
97
97
  rb_raise(rb_eStandardError, "Invalid Type, not a large tuple");
98
98
  }
99
-
99
+
100
100
  int arity = read_4(pData);
101
-
101
+
102
102
  VALUE array = rb_ary_new2(arity);
103
-
103
+
104
104
  int i;
105
105
  for(i = 0; i < arity; ++i) {
106
106
  rb_ary_store(array, i, read_any_raw(pData));
107
107
  }
108
-
108
+
109
109
  return array;
110
110
  }
111
111
 
@@ -113,18 +113,18 @@ VALUE read_list(unsigned char **pData) {
113
113
  if(read_1(pData) != ERL_LIST) {
114
114
  rb_raise(rb_eStandardError, "Invalid Type, not an erlang list");
115
115
  }
116
-
116
+
117
117
  int size = read_4(pData);
118
-
118
+
119
119
  VALUE array = rb_ary_new2(size);
120
-
120
+
121
121
  int i;
122
122
  for(i = 0; i < size; ++i) {
123
123
  rb_ary_store(array, i, read_any_raw(pData));
124
124
  }
125
-
125
+
126
126
  read_1(pData);
127
-
127
+
128
128
  return array;
129
129
  }
130
130
 
@@ -140,12 +140,12 @@ VALUE read_bin(unsigned char **pData) {
140
140
  if(read_1(pData) != ERL_BIN) {
141
141
  rb_raise(rb_eStandardError, "Invalid Type, not an erlang binary");
142
142
  }
143
-
143
+
144
144
  int length = read_4(pData);
145
-
145
+
146
146
  unsigned char buf[length + 1];
147
147
  read_string_raw(buf, pData, length);
148
-
148
+
149
149
  return rb_str_new2((char *) buf);
150
150
  }
151
151
 
@@ -153,19 +153,19 @@ VALUE read_string(unsigned char **pData) {
153
153
  if(read_1(pData) != ERL_STRING) {
154
154
  rb_raise(rb_eStandardError, "Invalid Type, not an erlang string");
155
155
  }
156
-
156
+
157
157
  int length = read_2(pData);
158
-
158
+
159
159
  unsigned char buf[length + 1];
160
160
  read_string_raw(buf, pData, length);
161
-
161
+
162
162
  VALUE array = rb_ary_new2(length);
163
-
163
+
164
164
  int i = 0;
165
165
  for(i; i < length; ++i) {
166
166
  rb_ary_store(array, i, INT2NUM(*(buf + i)));
167
167
  }
168
-
168
+
169
169
  return array;
170
170
  }
171
171
 
@@ -173,22 +173,29 @@ VALUE read_atom(unsigned char **pData) {
173
173
  if(read_1(pData) != ERL_ATOM) {
174
174
  rb_raise(rb_eStandardError, "Invalid Type, not an atom");
175
175
  }
176
-
176
+
177
177
  int length = read_2(pData);
178
-
178
+
179
179
  unsigned char buf[length + 1];
180
180
  read_string_raw(buf, pData, length);
181
-
182
- return ID2SYM(rb_intern((char *) buf));
181
+
182
+ // Erlang true and false are actually atoms
183
+ if(strncmp((char *) buf, "true", length) == 0) {
184
+ return Qtrue;
185
+ } else if(strncmp((char *) buf, "false", length) == 0) {
186
+ return Qfalse;
187
+ } else {
188
+ return ID2SYM(rb_intern((char *) buf));
189
+ }
183
190
  }
184
191
 
185
192
  VALUE read_small_int(unsigned char **pData) {
186
193
  if(read_1(pData) != ERL_SMALL_INT) {
187
194
  rb_raise(rb_eStandardError, "Invalid Type, not a small int");
188
195
  }
189
-
196
+
190
197
  int value = read_1(pData);
191
-
198
+
192
199
  return INT2FIX(value);
193
200
  }
194
201
 
@@ -196,15 +203,15 @@ VALUE read_int(unsigned char **pData) {
196
203
  if(read_1(pData) != ERL_INT) {
197
204
  rb_raise(rb_eStandardError, "Invalid Type, not an int");
198
205
  }
199
-
206
+
200
207
  long long value = read_4(pData);
201
-
208
+
202
209
  long long negative = ((value >> 31) & 0x1 == 1);
203
-
210
+
204
211
  if(negative) {
205
212
  value = (value - ((long long) 1 << 32));
206
213
  }
207
-
214
+
208
215
  return INT2FIX(value);
209
216
  }
210
217
 
@@ -212,27 +219,27 @@ VALUE read_small_bignum(unsigned char **pData) {
212
219
  if(read_1(pData) != ERL_SMALL_BIGNUM) {
213
220
  rb_raise(rb_eStandardError, "Invalid Type, not a small bignum");
214
221
  }
215
-
222
+
216
223
  unsigned int size = read_1(pData);
217
224
  unsigned int sign = read_1(pData);
218
-
225
+
219
226
  VALUE num = INT2NUM(0);
220
227
  VALUE tmp;
221
-
228
+
222
229
  unsigned char buf[size + 1];
223
230
  read_string_raw(buf, pData, size);
224
-
231
+
225
232
  int i;
226
233
  for(i = 0; i < size; ++i) {
227
234
  tmp = INT2FIX(*(buf + i));
228
235
  tmp = rb_funcall(tmp, rb_intern("<<"), 1, INT2NUM(i * 8));
229
236
  num = rb_funcall(num, rb_intern("+"), 1, tmp);
230
237
  }
231
-
238
+
232
239
  if(sign) {
233
240
  num = rb_funcall(num, rb_intern("*"), 1, INT2NUM(-1));
234
241
  }
235
-
242
+
236
243
  return num;
237
244
  }
238
245
 
@@ -240,28 +247,28 @@ VALUE read_large_bignum(unsigned char **pData) {
240
247
  if(read_1(pData) != ERL_LARGE_BIGNUM) {
241
248
  rb_raise(rb_eStandardError, "Invalid Type, not a small bignum");
242
249
  }
243
-
250
+
244
251
  unsigned int size = read_4(pData);
245
252
  unsigned int sign = read_1(pData);
246
-
253
+
247
254
  VALUE num = INT2NUM(0);
248
255
  VALUE tmp;
249
-
256
+
250
257
  unsigned char buf[size + 1];
251
258
  read_string_raw(buf, pData, size);
252
-
259
+
253
260
  int i;
254
261
  for(i = 0; i < size; ++i) {
255
262
  tmp = INT2FIX(*(buf + i));
256
263
  tmp = rb_funcall(tmp, rb_intern("<<"), 1, INT2NUM(i * 8));
257
-
264
+
258
265
  num = rb_funcall(num, rb_intern("+"), 1, tmp);
259
266
  }
260
-
267
+
261
268
  if(sign) {
262
269
  num = rb_funcall(num, rb_intern("*"), 1, INT2NUM(-1));
263
270
  }
264
-
271
+
265
272
  return num;
266
273
  }
267
274
 
@@ -269,12 +276,12 @@ VALUE read_float(unsigned char **pData) {
269
276
  if(read_1(pData) != ERL_FLOAT) {
270
277
  rb_raise(rb_eStandardError, "Invalid Type, not a float");
271
278
  }
272
-
279
+
273
280
  unsigned char buf[32];
274
281
  read_string_raw(buf, pData, 31);
275
-
282
+
276
283
  VALUE rString = rb_str_new2((char *) buf);
277
-
284
+
278
285
  return rb_funcall(rString, rb_intern("to_f"), 0);
279
286
  }
280
287
 
@@ -282,7 +289,7 @@ VALUE read_nil(unsigned char **pData) {
282
289
  if(read_1(pData) != ERL_NIL) {
283
290
  rb_raise(rb_eStandardError, "Invalid Type, not a nil list");
284
291
  }
285
-
292
+
286
293
  return rb_ary_new2(0);
287
294
  }
288
295
 
@@ -292,12 +299,12 @@ VALUE read_pid(unsigned char **pData) {
292
299
  if(read_1(pData) != ERL_PID) {
293
300
  rb_raise(rb_eStandardError, "Invalid Type, not a pid");
294
301
  }
295
-
302
+
296
303
  VALUE node = read_atom(pData);
297
304
  VALUE id = INT2NUM(read_4(pData));
298
305
  VALUE serial = INT2NUM(read_4(pData));
299
306
  VALUE creation = INT2FIX(read_1(pData));
300
-
307
+
301
308
  VALUE pid_class = rb_const_get(mErlectricity, rb_intern("Pid"));
302
309
  return rb_funcall(pid_class, rb_intern("new"), 4, node, id, serial, creation);
303
310
  }
@@ -306,17 +313,17 @@ VALUE read_new_reference(unsigned char **pData) {
306
313
  if(read_1(pData) != ERL_NEW_REF) {
307
314
  rb_raise(rb_eStandardError, "Invalid Type, not a new-style reference");
308
315
  }
309
-
316
+
310
317
  int size = read_2(pData);
311
318
  VALUE node = read_atom(pData);
312
319
  VALUE creation = INT2FIX(read_1(pData));
313
-
320
+
314
321
  VALUE id = rb_ary_new2(size);
315
322
  int i;
316
323
  for(i = 0; i < size; ++i) {
317
324
  rb_ary_store(id, i, INT2NUM(read_4(pData)));
318
325
  }
319
-
326
+
320
327
  VALUE newref_class = rb_const_get(mErlectricity, rb_intern("NewReference"));
321
328
  return rb_funcall(newref_class, rb_intern("new"), 3, node, creation, id);
322
329
  }
@@ -371,21 +378,21 @@ VALUE read_any_raw(unsigned char **pData) {
371
378
  return Qnil;
372
379
  }
373
380
 
374
- VALUE method_read_any_from(VALUE klass, VALUE rString) {
381
+ VALUE method_decode(VALUE klass, VALUE rString) {
375
382
  unsigned char *data = (unsigned char *) StringValuePtr(rString);
376
-
383
+
377
384
  unsigned char **pData = &data;
378
-
385
+
379
386
  // check protocol version
380
387
  if(read_1(pData) != ERL_VERSION) {
381
388
  rb_raise(rb_eStandardError, "Bad Magic");
382
389
  }
383
-
390
+
384
391
  return read_any_raw(pData);
385
392
  }
386
393
 
387
394
  void Init_decoder() {
388
395
  mErlectricity = rb_const_get(rb_cObject, rb_intern("Erlectricity"));
389
396
  cDecoder = rb_define_class_under(mErlectricity, "Decoder", rb_cObject);
390
- rb_define_singleton_method(cDecoder, "read_any_from", method_read_any_from, 1);
391
- }
397
+ rb_define_singleton_method(cDecoder, "decode", method_decode, 1);
398
+ }
@@ -1,50 +1,65 @@
1
1
  module Erlectricity
2
2
  class Condition
3
-
3
+ def self.for(a)
4
+ case a
5
+ when Condition then a
6
+ when Class then TypeCondition.new(a)
7
+ else StaticCondition.new(a)
8
+ end
9
+ end
10
+
4
11
  def initialize
5
12
  end
6
-
13
+
7
14
  def binding_for(arg)
8
15
  nil
9
16
  end
10
-
17
+
11
18
  def satisfies?(arg)
12
19
  false
13
20
  end
14
-
21
+
15
22
  alias === satisfies?
16
23
  end
17
24
 
18
25
  module Conditions
19
- def atom()
26
+ def atom
20
27
  TypeCondition.new(Symbol)
21
28
  end
22
-
23
- def any()
29
+
30
+ def any
24
31
  TypeCondition.new(Object)
25
32
  end
26
-
27
- def number()
33
+
34
+ def number
28
35
  TypeCondition.new(Fixnum)
29
36
  end
30
-
31
- def pid()
37
+
38
+ def pid
32
39
  TypeCondition.new(Erlectricity::Pid)
33
40
  end
34
-
35
- def string()
36
- TypeCondition.new(String)
41
+
42
+ def ref
43
+ TypeCondition.new(Erlectricity::NewReference)
44
+ end
45
+
46
+ def string
47
+ TypeCondition.new(String)
37
48
  end
38
-
39
- def list()
40
- TypeCondition.new(Array)
49
+
50
+ def list
51
+ TypeCondition.new(Array)
41
52
  end
42
-
43
- def hash()
53
+
54
+ def hash
44
55
  HashCondition.new()
45
56
  end
57
+
58
+ def boolean
59
+ BooleanCondition.new()
60
+ end
46
61
  end
47
-
62
+
48
63
  extend Conditions
49
64
  end
50
65
 
@@ -0,0 +1,11 @@
1
+ module Erlectricity
2
+ class BooleanCondition < Condition
3
+ def satisfies?(arg)
4
+ [TrueClass, FalseClass].include?(arg.class)
5
+ end
6
+
7
+ def binding_for(arg)
8
+ arg
9
+ end
10
+ end
11
+ end
@@ -1,14 +1,13 @@
1
1
  module Erlectricity
2
- class HashCondition < Condition
2
+ class HashCondition < Condition
3
+ def satisfies?(arg)
4
+ return false unless arg.class == Array
5
+ arg.all? { |x| x.class == Array && x.length == 2 }
6
+ end
3
7
 
4
- def satisfies?(arg)
5
- return false unless arg.class == Array
6
- arg.all?{|x| x.class == Array && x.length == 2}
8
+ def binding_for(arg)
9
+ flattened = arg.inject([]) { |memo, kv| memo + kv }
10
+ Hash[*flattened]
11
+ end
7
12
  end
8
-
9
- def binding_for(arg)
10
- flattened = arg.inject([]){|memo, kv| memo + kv}
11
- Hash[*flattened]
12
- end
13
- end
14
13
  end
@@ -1,13 +1,34 @@
1
1
  module Erlectricity
2
- class StaticCondition < Condition
3
- attr_accessor :value
4
- def initialize(value)
5
- self.value = value
6
- end
7
-
8
- def satisfies?(arg)
9
- arg.eql? value
10
- end
2
+ class StaticCondition < Condition
3
+ attr_accessor :value
4
+ def initialize(value)
5
+ if value.is_a?(Array)
6
+ self.value = value.map do |v|
7
+ Condition.for(v)
8
+ end
9
+ else
10
+ self.value = value
11
+ end
12
+ end
11
13
 
14
+ def satisfies?(arg)
15
+ if value.is_a?(Array)
16
+ return false unless arg.is_a?(Array)
17
+ return false if value.length != arg.length
18
+ value.zip(arg).all? do |l, r|
19
+ l.respond_to?(:satisfies?) ? l.satisfies?(r) : l.eql?(r)
20
+ end
21
+ else
22
+ arg.eql?(value)
23
+ end
24
+ end
25
+
26
+ def binding_for(arg)
27
+ if value.is_a?(Array)
28
+ value.zip(arg).map { |l, r| l.binding_for(r) }.compact
29
+ else
30
+ nil
31
+ end
32
+ end
33
+ end
12
34
  end
13
- end
@@ -1,17 +1,17 @@
1
1
  module Erlectricity
2
- class TypeCondition < Condition
3
- attr_accessor :type
4
-
5
- def initialize(type)
6
- self.type = type
2
+ class TypeCondition < Condition
3
+ attr_accessor :type
4
+
5
+ def initialize(type)
6
+ self.type = type
7
+ end
8
+
9
+ def satisfies?(arg)
10
+ arg.is_a?(self.type)
11
+ end
12
+
13
+ def binding_for(arg)
14
+ arg
15
+ end
7
16
  end
8
-
9
- def satisfies?(arg)
10
- arg.is_a? self.type
11
- end
12
-
13
- def binding_for(arg)
14
- arg
15
- end
16
- end
17
17
  end