erlectricity 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CONTRIBUTORS ADDED
@@ -0,0 +1,2 @@
1
+ Tom Preston-Werner
2
+ - provided the C extension that replaces the ruby decoder
data/History.txt ADDED
@@ -0,0 +1 @@
1
+
data/Manifest.txt CHANGED
@@ -1,3 +1,5 @@
1
+ CONTRIBUTORS
2
+ History.txt
1
3
  Manifest.txt
2
4
  README.txt
3
5
  Rakefile
@@ -8,6 +10,8 @@ examples/gruff/stat_run.erl
8
10
  examples/gruff/stat_writer.erl
9
11
  examples/tinderl/tinderl.erl
10
12
  examples/tinderl/tinderl.rb
13
+ ext/decoder.c
14
+ ext/extconf.rb
11
15
  lib/erlectricity.rb
12
16
  lib/erlectricity/condition.rb
13
17
  lib/erlectricity/conditions/hash.rb
@@ -19,11 +23,11 @@ lib/erlectricity/encoder.rb
19
23
  lib/erlectricity/errors/decode_error.rb
20
24
  lib/erlectricity/errors/encode_error.rb
21
25
  lib/erlectricity/errors/erlectricity_error.rb
22
- lib/erlectricity/match_context.rb
23
26
  lib/erlectricity/matcher.rb
24
27
  lib/erlectricity/port.rb
25
28
  lib/erlectricity/receiver.rb
26
29
  lib/erlectricity/types/function.rb
30
+ lib/erlectricity/types/list.rb
27
31
  lib/erlectricity/types/new_function.rb
28
32
  lib/erlectricity/types/new_reference.rb
29
33
  lib/erlectricity/types/pid.rb
data/Rakefile CHANGED
@@ -49,7 +49,7 @@ hoe = Hoe.new(GEM_NAME, VERS) do |p|
49
49
 
50
50
  # == Optional
51
51
  p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
52
- #p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
52
+ p.extra_deps = [ ] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
53
53
  #p.spec_extras = {} # A hash of extra values to set in the gemspec.
54
54
  end
55
55
 
@@ -1,36 +1,36 @@
1
1
  $:.unshift(File.dirname(__FILE__) + "/../../lib/")
2
- require 'rubygems'
3
2
  require 'erlectricity'
3
+ require 'rubygems'
4
4
  require 'gruff'
5
5
 
6
- receive do
6
+ receive do |f|
7
7
 
8
8
 
9
9
 
10
- match(:plot, string(:name), atom(:style), string(:font)) do
10
+ f.when(:plot, String, Symbol, String) do |name, style, font|
11
11
  graph = Gruff.const_get(style).new
12
12
  graph.title = name
13
13
  graph.font = font
14
14
  graph.legend_font_size = 10
15
15
 
16
16
 
17
- receive do
18
- match(:data, atom(:name), list(:points)) do
17
+ f.receive do |g|
18
+ g.when(:data, Symbol, Array) do |name, points|
19
19
  graph.data name, points
20
- receive_loop
20
+ g.receive_loop
21
21
  end
22
22
 
23
- match(:labels, hash(:label_data)) do
23
+ g.when(:labels, Erl.hash) do |label_data|
24
24
  graph.labels = label_data
25
- receive_loop
25
+ g.receive_loop
26
26
  end
27
27
 
28
- match(:end){ :ok }
28
+ g.when(:end){ :ok }
29
29
  end
30
30
 
31
31
 
32
- send! :result, graph.to_blob
33
- receive_loop
32
+ f.send! :result, graph.to_blob
33
+ f.receive_loop
34
34
  end
35
35
 
36
36
  end
@@ -12,7 +12,11 @@ start(Domain, Email, Password, Room) ->
12
12
 
13
13
  stop() -> tinderl ! stop.
14
14
 
15
+
16
+ speak(String) when is_list(String) -> speak(list_to_binary(String));
15
17
  speak(String) when is_binary(String) -> tinderl ! {speak, self(), String}.
18
+
19
+ paste(String) when is_list(String) -> speak(list_to_binary(String));
16
20
  paste(String) when is_binary(String) -> tinderl ! {paste, self(), String}.
17
21
 
18
22
  port_loop(Port) ->
@@ -1,6 +1,6 @@
1
1
  $:.unshift(File.dirname(__FILE__) + "/../../lib/")
2
- require 'rubygems'
3
2
  require 'erlectricity'
3
+ require 'rubygems'
4
4
  require 'tinder'
5
5
 
6
6
  domain, email, password, room_name = *ARGV
@@ -8,15 +8,19 @@ campfire = Tinder::Campfire.new domain
8
8
  campfire.login email, password
9
9
  room = campfire.find_room_by_name room_name
10
10
 
11
- receive do
12
- match(:speak, any(:comment)) do
11
+ receive do |f|
12
+ f.when(:speak, Any) do |comment|
13
13
  room.speak comment
14
- receive_loop
14
+ f.receive_loop
15
15
  end
16
16
 
17
- match(:paste, any(:comment)) do
17
+ f.when(:paste, Any) do |comment|
18
18
  room.paste comment
19
- receive_loop
19
+ f.receive_loop
20
+ end
21
+
22
+ f.when(Any) do |obj|
23
+ STDERR.write obj.inspect
20
24
  end
21
25
  end
22
26
 
data/ext/decoder.c ADDED
@@ -0,0 +1,389 @@
1
+ #include "ruby.h"
2
+ #include <string.h>
3
+
4
+ #define ERL_VERSION 131
5
+ #define ERL_SMALL_INT 97
6
+ #define ERL_INT 98
7
+ #define ERL_SMALL_BIGNUM 110
8
+ #define ERL_LARGE_BIGNUM 111
9
+ #define ERL_FLOAT 99
10
+ #define ERL_ATOM 100
11
+ #define ERL_REF 101
12
+ #define ERL_NEW_REF 114
13
+ #define ERL_PORT 102
14
+ #define ERL_PID 103
15
+ #define ERL_SMALL_TUPLE 104
16
+ #define ERL_LARGE_TUPLE 105
17
+ #define ERL_NIL 106
18
+ #define ERL_STRING 107
19
+ #define ERL_LIST 108
20
+ #define ERL_BIN 109
21
+ #define ERL_FUN 117
22
+ #define ERL_NEW_FUN 112
23
+
24
+ static VALUE mErlectricity;
25
+ static VALUE cDecoder;
26
+ void Init_decoder();
27
+
28
+ VALUE method_read_any_from(VALUE klass, VALUE rString);
29
+
30
+ VALUE read_any_raw(unsigned char **pData);
31
+
32
+ // checkers
33
+
34
+ void check_int(int num) {
35
+ char buf[17];
36
+ sprintf(buf, "%u", num);
37
+ rb_raise(rb_eStandardError, buf);
38
+ }
39
+
40
+ void check_str(char *str) {
41
+ rb_raise(rb_eStandardError, str);
42
+ }
43
+
44
+ // string peekers/readers
45
+
46
+ unsigned int peek_1(unsigned char **pData) {
47
+ return (unsigned int) **pData;
48
+ }
49
+
50
+ unsigned int peek_2(unsigned char **pData) {
51
+ return (unsigned int) ((**pData << 8) + *(*pData + 1));
52
+ }
53
+
54
+ unsigned int peek_4(unsigned char **pData) {
55
+ return (unsigned int) ((**pData << 24) + (*(*pData + 1) << 16) + (*(*pData + 2) << 8) + *(*pData + 3));
56
+ }
57
+
58
+ unsigned int read_1(unsigned char **pData) {
59
+ unsigned int val = peek_1(pData);
60
+ *pData += 1;
61
+ return val;
62
+ }
63
+
64
+ unsigned int read_2(unsigned char **pData) {
65
+ unsigned int val = peek_2(pData);
66
+ *pData += 2;
67
+ return val;
68
+ }
69
+
70
+ unsigned int read_4(unsigned char **pData) {
71
+ unsigned int val = peek_4(pData);
72
+ *pData += 4;
73
+ return val;
74
+ }
75
+
76
+ // tuples, lists
77
+
78
+ VALUE read_small_tuple(unsigned char **pData) {
79
+ if(read_1(pData) != ERL_SMALL_TUPLE) {
80
+ rb_raise(rb_eStandardError, "Invalid Type, not a small tuple");
81
+ }
82
+
83
+ int arity = read_1(pData);
84
+
85
+ VALUE array = rb_ary_new2(arity);
86
+
87
+ int i;
88
+ for(i = 0; i < arity; ++i) {
89
+ rb_ary_store(array, i, read_any_raw(pData));
90
+ }
91
+
92
+ return array;
93
+ }
94
+
95
+ VALUE read_large_tuple(unsigned char **pData) {
96
+ if(read_1(pData) != ERL_LARGE_TUPLE) {
97
+ rb_raise(rb_eStandardError, "Invalid Type, not a large tuple");
98
+ }
99
+
100
+ int arity = read_4(pData);
101
+
102
+ VALUE array = rb_ary_new2(arity);
103
+
104
+ int i;
105
+ for(i = 0; i < arity; ++i) {
106
+ rb_ary_store(array, i, read_any_raw(pData));
107
+ }
108
+
109
+ return array;
110
+ }
111
+
112
+ VALUE read_list(unsigned char **pData) {
113
+ if(read_1(pData) != ERL_LIST) {
114
+ rb_raise(rb_eStandardError, "Invalid Type, not an erlang list");
115
+ }
116
+
117
+ int size = read_4(pData);
118
+
119
+ VALUE array = rb_ary_new2(size);
120
+
121
+ int i;
122
+ for(i = 0; i < size; ++i) {
123
+ rb_ary_store(array, i, read_any_raw(pData));
124
+ }
125
+
126
+ return array;
127
+ }
128
+
129
+ // primitives
130
+
131
+ void read_string_raw(unsigned char *dest, unsigned char **pData, int length) {
132
+ memcpy((char *) dest, (char *) *pData, length);
133
+ *(dest + length) = (unsigned char) 0;
134
+ *pData += length;
135
+ }
136
+
137
+ VALUE read_bin(unsigned char **pData) {
138
+ if(read_1(pData) != ERL_BIN) {
139
+ rb_raise(rb_eStandardError, "Invalid Type, not an erlang binary");
140
+ }
141
+
142
+ int length = read_4(pData);
143
+
144
+ unsigned char buf[length + 1];
145
+ read_string_raw(buf, pData, length);
146
+
147
+ return rb_str_new2((char *) buf);
148
+ }
149
+
150
+ VALUE read_string(unsigned char **pData) {
151
+ if(read_1(pData) != ERL_STRING) {
152
+ rb_raise(rb_eStandardError, "Invalid Type, not an erlang string");
153
+ }
154
+
155
+ int length = read_2(pData);
156
+
157
+ unsigned char buf[length + 1];
158
+ read_string_raw(buf, pData, length);
159
+
160
+ VALUE array = rb_ary_new2(length);
161
+
162
+ int i = 0;
163
+ for(i; i < length; ++i) {
164
+ rb_ary_store(array, i, INT2NUM(*(buf + i)));
165
+ }
166
+
167
+ return array;
168
+ }
169
+
170
+ VALUE read_atom(unsigned char **pData) {
171
+ if(read_1(pData) != ERL_ATOM) {
172
+ rb_raise(rb_eStandardError, "Invalid Type, not an atom");
173
+ }
174
+
175
+ int length = read_2(pData);
176
+
177
+ unsigned char buf[length + 1];
178
+ read_string_raw(buf, pData, length);
179
+
180
+ return ID2SYM(rb_intern((char *) buf));
181
+ }
182
+
183
+ VALUE read_small_int(unsigned char **pData) {
184
+ if(read_1(pData) != ERL_SMALL_INT) {
185
+ rb_raise(rb_eStandardError, "Invalid Type, not a small int");
186
+ }
187
+
188
+ int value = read_1(pData);
189
+
190
+ return INT2FIX(value);
191
+ }
192
+
193
+ VALUE read_int(unsigned char **pData) {
194
+ if(read_1(pData) != ERL_INT) {
195
+ rb_raise(rb_eStandardError, "Invalid Type, not an int");
196
+ }
197
+
198
+ long long value = read_4(pData);
199
+
200
+ long long negative = ((value >> 31) & 0x1 == 1);
201
+
202
+ if(negative) {
203
+ value = (value - ((long long) 1 << 32));
204
+ }
205
+
206
+ return INT2FIX(value);
207
+ }
208
+
209
+ VALUE read_small_bignum(unsigned char **pData) {
210
+ if(read_1(pData) != ERL_SMALL_BIGNUM) {
211
+ rb_raise(rb_eStandardError, "Invalid Type, not a small bignum");
212
+ }
213
+
214
+ unsigned int size = read_1(pData);
215
+ unsigned int sign = read_1(pData);
216
+
217
+ VALUE num = INT2NUM(0);
218
+ VALUE tmp;
219
+
220
+ unsigned char buf[size + 1];
221
+ read_string_raw(buf, pData, size);
222
+
223
+ int i;
224
+ for(i = 0; i < size; ++i) {
225
+ tmp = INT2FIX(*(buf + i));
226
+ tmp = rb_funcall(tmp, rb_intern("<<"), 1, INT2NUM(i * 8));
227
+ num = rb_funcall(num, rb_intern("+"), 1, tmp);
228
+ }
229
+
230
+ if(sign) {
231
+ num = rb_funcall(num, rb_intern("*"), 1, INT2NUM(-1));
232
+ }
233
+
234
+ return num;
235
+ }
236
+
237
+ VALUE read_large_bignum(unsigned char **pData) {
238
+ if(read_1(pData) != ERL_LARGE_BIGNUM) {
239
+ rb_raise(rb_eStandardError, "Invalid Type, not a small bignum");
240
+ }
241
+
242
+ unsigned int size = read_4(pData);
243
+ unsigned int sign = read_1(pData);
244
+
245
+ VALUE num = INT2NUM(0);
246
+ VALUE tmp;
247
+
248
+ unsigned char buf[size + 1];
249
+ read_string_raw(buf, pData, size);
250
+
251
+ int i;
252
+ for(i = 0; i < size; ++i) {
253
+ tmp = INT2FIX(*(buf + i));
254
+ tmp = rb_funcall(tmp, rb_intern("<<"), 1, INT2NUM(i * 8));
255
+
256
+ num = rb_funcall(num, rb_intern("+"), 1, tmp);
257
+ }
258
+
259
+ if(sign) {
260
+ num = rb_funcall(num, rb_intern("*"), 1, INT2NUM(-1));
261
+ }
262
+
263
+ return num;
264
+ }
265
+
266
+ VALUE read_float(unsigned char **pData) {
267
+ if(read_1(pData) != ERL_FLOAT) {
268
+ rb_raise(rb_eStandardError, "Invalid Type, not a float");
269
+ }
270
+
271
+ unsigned char buf[32];
272
+ read_string_raw(buf, pData, 31);
273
+
274
+ VALUE rString = rb_str_new2((char *) buf);
275
+
276
+ return rb_funcall(rString, rb_intern("to_f"), 0);
277
+ }
278
+
279
+ VALUE read_nil(unsigned char **pData) {
280
+ if(read_1(pData) != ERL_NIL) {
281
+ rb_raise(rb_eStandardError, "Invalid Type, not a nil list");
282
+ }
283
+
284
+ return rb_ary_new2(0);
285
+ }
286
+
287
+ // specials
288
+
289
+ VALUE read_pid(unsigned char **pData) {
290
+ if(read_1(pData) != ERL_PID) {
291
+ rb_raise(rb_eStandardError, "Invalid Type, not a pid");
292
+ }
293
+
294
+ VALUE node = read_atom(pData);
295
+ VALUE id = INT2NUM(read_4(pData));
296
+ VALUE serial = INT2NUM(read_4(pData));
297
+ VALUE creation = INT2FIX(read_1(pData));
298
+
299
+ VALUE pid_class = rb_const_get(mErlectricity, rb_intern("Pid"));
300
+ return rb_funcall(pid_class, rb_intern("new"), 4, node, id, serial, creation);
301
+ }
302
+
303
+ VALUE read_new_reference(unsigned char **pData) {
304
+ if(read_1(pData) != ERL_NEW_REF) {
305
+ rb_raise(rb_eStandardError, "Invalid Type, not a new-style reference");
306
+ }
307
+
308
+ int size = read_2(pData);
309
+ VALUE node = read_atom(pData);
310
+ VALUE creation = INT2FIX(read_1(pData));
311
+
312
+ VALUE id = rb_ary_new2(size);
313
+ int i;
314
+ for(i = 0; i < size; ++i) {
315
+ rb_ary_store(id, i, INT2NUM(read_4(pData)));
316
+ }
317
+
318
+ VALUE newref_class = rb_const_get(mErlectricity, rb_intern("NewReference"));
319
+ return rb_funcall(newref_class, rb_intern("new"), 3, node, creation, id);
320
+ }
321
+
322
+ // read_any_raw
323
+
324
+ VALUE read_any_raw(unsigned char **pData) {
325
+ switch(peek_1(pData)) {
326
+ case ERL_SMALL_INT:
327
+ return read_small_int(pData);
328
+ break;
329
+ case ERL_INT:
330
+ return read_int(pData);
331
+ break;
332
+ case ERL_FLOAT:
333
+ return read_float(pData);
334
+ break;
335
+ case ERL_ATOM:
336
+ return read_atom(pData);
337
+ break;
338
+ case ERL_PID:
339
+ return read_pid(pData);
340
+ break;
341
+ case ERL_SMALL_TUPLE:
342
+ return read_small_tuple(pData);
343
+ break;
344
+ case ERL_LARGE_TUPLE:
345
+ return read_large_tuple(pData);
346
+ break;
347
+ case ERL_NIL:
348
+ return read_nil(pData);
349
+ break;
350
+ case ERL_STRING:
351
+ return read_string(pData);
352
+ break;
353
+ case ERL_LIST:
354
+ return read_list(pData);
355
+ break;
356
+ case ERL_BIN:
357
+ return read_bin(pData);
358
+ break;
359
+ case ERL_SMALL_BIGNUM:
360
+ return read_small_bignum(pData);
361
+ break;
362
+ case ERL_LARGE_BIGNUM:
363
+ return read_large_bignum(pData);
364
+ break;
365
+ case ERL_NEW_REF:
366
+ return read_new_reference(pData);
367
+ break;
368
+ }
369
+ return Qnil;
370
+ }
371
+
372
+ VALUE method_read_any_from(VALUE klass, VALUE rString) {
373
+ unsigned char *data = (unsigned char *) StringValuePtr(rString);
374
+
375
+ unsigned char **pData = &data;
376
+
377
+ // check protocol version
378
+ if(read_1(pData) != ERL_VERSION) {
379
+ rb_raise(rb_eStandardError, "Bad Magic");
380
+ }
381
+
382
+ return read_any_raw(pData);
383
+ }
384
+
385
+ void Init_decoder() {
386
+ mErlectricity = rb_const_get(rb_cObject, rb_intern("Erlectricity"));
387
+ cDecoder = rb_define_class_under(mErlectricity, "Decoder", rb_cObject);
388
+ rb_define_singleton_method(cDecoder, "read_any_from", method_read_any_from, 1);
389
+ }
data/ext/extconf.rb ADDED
@@ -0,0 +1,11 @@
1
+ # Loads mkmf which is used to make makefiles for Ruby extensions
2
+ require 'mkmf'
3
+
4
+ # Give it a name
5
+ extension_name = 'decoder'
6
+
7
+ # The destination
8
+ dir_config(extension_name)
9
+
10
+ # Do the work
11
+ create_makefile(extension_name)
data/lib/erlectricity.rb CHANGED
@@ -3,13 +3,20 @@ require 'erlectricity/constants'
3
3
  require 'erlectricity/types/new_reference'
4
4
  require 'erlectricity/types/pid'
5
5
  require 'erlectricity/types/function'
6
+ require 'erlectricity/types/list'
7
+
8
+ begin
9
+ #try to load the decoder C extension
10
+ require 'decoder'
11
+ rescue LoadError
12
+ #load the pure ruby instead
13
+ require 'erlectricity/decoder'
14
+ end
6
15
 
7
- require 'erlectricity/decoder'
8
16
  require 'erlectricity/encoder'
9
17
 
10
18
  require 'erlectricity/port'
11
19
  require 'erlectricity/matcher'
12
- require 'erlectricity/match_context'
13
20
 
14
21
  require 'erlectricity/condition'
15
22
  require 'erlectricity/conditions/hash'
@@ -21,3 +28,5 @@ require 'erlectricity/receiver'
21
28
  require 'erlectricity/errors/erlectricity_error'
22
29
  require 'erlectricity/errors/decode_error'
23
30
  require 'erlectricity/errors/encode_error'
31
+
32
+ Erl = Erlectricity
@@ -1,48 +1,51 @@
1
1
  module Erlectricity
2
2
  class Condition
3
- attr_accessor :binding_name
4
3
 
5
- def initialize(binding_name=nil)
6
- self.binding_name = binding_name
4
+ def initialize
7
5
  end
8
6
 
9
- def bindings_for(arg)
10
- {}
7
+ def binding_for(arg)
8
+ nil
11
9
  end
12
10
 
13
11
  def satisfies?(arg)
14
12
  false
15
13
  end
16
-
14
+
15
+ alias === satisfies?
17
16
  end
18
17
 
19
18
  module Conditions
20
- def atom(name=nil)
21
- TypeCondition.new(Symbol, name)
19
+ def atom()
20
+ TypeCondition.new(Symbol)
22
21
  end
23
22
 
24
- def any(name=nil)
25
- TypeCondition.new(Object, name)
23
+ def any()
24
+ TypeCondition.new(Object)
26
25
  end
27
26
 
28
- def number(name=nil)
29
- TypeCondition.new(Fixnum, name)
27
+ def number()
28
+ TypeCondition.new(Fixnum)
30
29
  end
31
30
 
32
- def pid(name=nil)
33
- TypeCondition.new(Erlectricity::Pid, name)
31
+ def pid()
32
+ TypeCondition.new(Erlectricity::Pid)
34
33
  end
35
34
 
36
- def string(name=nil)
37
- TypeCondition.new(String, name)
35
+ def string()
36
+ TypeCondition.new(String)
38
37
  end
39
38
 
40
- def list(name=nil)
41
- TypeCondition.new(Array, name)
39
+ def list()
40
+ TypeCondition.new(Array)
42
41
  end
43
42
 
44
- def hash(name=nil)
45
- HashCondition.new(name)
43
+ def hash()
44
+ HashCondition.new()
46
45
  end
47
46
  end
48
- end
47
+
48
+ extend Conditions
49
+ end
50
+
51
+ Any = Object
@@ -6,10 +6,9 @@ class HashCondition < Condition
6
6
  arg.all?{|x| x.class == Array && x.length == 2}
7
7
  end
8
8
 
9
- def bindings_for(arg)
10
- return {} unless self.binding_name
9
+ def binding_for(arg)
11
10
  flattened = arg.inject([]){|memo, kv| memo + kv}
12
- {self.binding_name => Hash[*flattened]}
11
+ Hash[*flattened]
13
12
  end
14
13
  end
15
14
  end
@@ -1,17 +1,13 @@
1
1
  module Erlectricity
2
2
  class StaticCondition < Condition
3
3
  attr_accessor :value
4
- def initialize(value, name=nil)
4
+ def initialize(value)
5
5
  self.value = value
6
- super(name)
7
6
  end
8
7
 
9
8
  def satisfies?(arg)
10
9
  arg.eql? value
11
10
  end
12
-
13
- def bindings_for(arg)
14
- {}
15
- end
11
+
16
12
  end
17
13
  end
@@ -2,18 +2,16 @@ module Erlectricity
2
2
  class TypeCondition < Condition
3
3
  attr_accessor :type
4
4
 
5
- def initialize(type, name=nil)
5
+ def initialize(type)
6
6
  self.type = type
7
- super(name)
8
7
  end
9
8
 
10
9
  def satisfies?(arg)
11
10
  arg.is_a? self.type
12
11
  end
13
12
 
14
- def bindings_for(arg)
15
- return {} unless self.binding_name
16
- {self.binding_name => arg}
13
+ def binding_for(arg)
14
+ arg
17
15
  end
18
16
  end
19
17
  end
@@ -19,6 +19,7 @@ class Encoder
19
19
  when Float then write_float(obj)
20
20
  when Erlectricity::NewReference then write_new_reference(obj)
21
21
  when Erlectricity::Pid then write_pid(obj)
22
+ when Erlectricity::List then write_list(obj)
22
23
  when Array then write_tuple(obj)
23
24
  when String then write_binary(obj)
24
25
  else
@@ -106,7 +107,6 @@ class Encoder
106
107
  fail(data) unless data.is_a? Array
107
108
  write_1 NIL and return if data.empty?
108
109
 
109
- #NOTE: we do not ever encode as the string format.
110
110
  write_1 LIST
111
111
  write_4 data.length
112
112
  data.each{|e| write_any_raw e }
@@ -10,10 +10,8 @@ class Matcher
10
10
  end
11
11
 
12
12
  def run(arg)
13
- context = MatchContext.new(self.receiver)
14
-
15
- populate_context context, arg
16
- context.instance_eval &block
13
+ args = get_bound arg
14
+ block.call *args
17
15
  end
18
16
 
19
17
  def matches?(arg)
@@ -28,33 +26,13 @@ class Matcher
28
26
 
29
27
 
30
28
  private
31
- def populate_context(context, arg)
29
+
30
+ def get_bound(arg)
32
31
  if @condition.is_a?(Array) && arg.is_a?(Array)
33
- @condition.zip(arg).all?{|l,r| set_binding(context, l, r)}
32
+ @condition.zip(arg).map{|l,r| l.binding_for r}.compact
34
33
  else
35
- set_binding(context, condition, arg)
34
+ @condition.binding_for(arg)
36
35
  end
37
36
  end
38
-
39
- def set_binding(context, condition, arg)
40
- condition.bindings_for(arg).each do |k, v|
41
- add_to_context(context, k, v)
42
- end
43
- end
44
-
45
- def add_to_context(context, name, value)
46
- return if name.nil?
47
-
48
- context.instance_eval <<-EOS
49
- def #{name}
50
- @#{name}
51
- end
52
- def #{name}= (value)
53
- @#{name} = value
54
- end
55
- EOS
56
-
57
- context.send(:"#{name}=", value)
58
- end
59
37
  end
60
38
  end
@@ -1,6 +1,5 @@
1
1
  module Erlectricity
2
2
  class Receiver
3
- include Conditions
4
3
 
5
4
  attr_accessor :port
6
5
  attr_accessor :parent
@@ -13,7 +12,7 @@ class Receiver
13
12
  @port = port
14
13
  @parent = parent
15
14
  @matchers = []
16
- instance_eval &block if block
15
+ block.call self if block
17
16
  end
18
17
 
19
18
  def process(arg)
@@ -27,8 +26,14 @@ class Receiver
27
26
  end
28
27
  end
29
28
 
30
- def match(*args, &block)
31
- args = args.map{|a| a.is_a?(Condition) ? a : StaticCondition.new(a)}
29
+ def when(*args, &block)
30
+ args = args.map do |a|
31
+ case a
32
+ when Condition then a
33
+ when Class then TypeCondition.new(a)
34
+ else StaticCondition.new(a)
35
+ end
36
+ end
32
37
 
33
38
  args = args.first if args.length == 1
34
39
  @matchers << Matcher.new(self, args, block)
@@ -0,0 +1 @@
1
+ class Erlectricity::List < Array ; end
@@ -1,7 +1,7 @@
1
1
  module Erlectricity #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 1
4
+ MINOR = 2
5
5
  TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
@@ -7,16 +7,16 @@ context "Erlectricity::StaticConditions" do
7
7
  Erlectricity::StaticCondition.new(3).satisfies?(3).should == true
8
8
  end
9
9
 
10
- specify "should not satisfy on diffeent values" do
10
+ specify "should not satisfy on different values" do
11
11
  Erlectricity::StaticCondition.new(:foo).satisfies?("foo").should == false
12
12
  Erlectricity::StaticCondition.new([:foo]).satisfies?(:foo).should == false
13
13
  Erlectricity::StaticCondition.new(Object.new).satisfies?(Object.new).should == false
14
14
  Erlectricity::StaticCondition.new(3).satisfies?(3.0).should == false
15
15
  end
16
16
 
17
- specify "should not produce any bindings, even if a name is supplied" do
18
- s = Erlectricity::StaticCondition.new(:foo, :bound_name)
19
- s.bindings_for(:foo).should == {}
17
+ specify "should not produce any bindings" do
18
+ s = Erlectricity::StaticCondition.new(:foo)
19
+ s.binding_for(:foo).should == nil
20
20
  end
21
21
  end
22
22
 
@@ -42,17 +42,12 @@ context "Erlectricity::TypeConditions" do
42
42
  Erlectricity::TypeCondition.new(Fixnum).satisfies?(3.0).should == false
43
43
  end
44
44
 
45
- specify "should bind the arg to the name specified with no transormations" do
46
- s = Erlectricity::TypeCondition.new(Symbol, :bound_name)
47
- s.bindings_for(:foo).should == {:bound_name => :foo}
48
- s.bindings_for(:bar).should == {:bound_name => :bar}
49
- end
50
-
51
- specify "should not bind anything if no binding name is specified" do
52
-
45
+ specify "should bind the arg with no transormations" do
53
46
  s = Erlectricity::TypeCondition.new(Symbol)
54
- s.bindings_for(:foo).should == {}
47
+ s.binding_for(:foo).should == :foo
48
+ s.binding_for(:bar).should == :bar
55
49
  end
50
+
56
51
  end
57
52
 
58
53
  context "Erlectricity::HashConditions" do
@@ -71,8 +66,8 @@ context "Erlectricity::HashConditions" do
71
66
  Erlectricity::HashCondition.new.satisfies?(3.0).should == false
72
67
  end
73
68
 
74
- specify "should product a binder" do
75
- s = Erlectricity::HashCondition.new(:bound_name)
76
- s.bindings_for([[:foo, 3], [:bar, [3,4,5]]]).should == {:bound_name => {:foo => 3, :bar => [3,4,5] }}
69
+ specify "should bind to a Hash" do
70
+ s = Erlectricity::HashCondition.new()
71
+ s.binding_for([[:foo, 3], [:bar, [3,4,5]]]).should == {:foo => 3, :bar => [3,4,5] }
77
72
  end
78
73
  end
data/test/decode_spec.rb CHANGED
@@ -1,16 +1,7 @@
1
1
  require File.dirname(__FILE__) + '/test_helper.rb'
2
2
 
3
- context "The byte reader attached to decoder" do
4
- specify "should not advance the stream when peeking unless there arent enough bytes available" do
5
- @decoder = Erlectricity::Decoder.new(StringIO.new('abcdefghijklmnopqrstuvwxyz'))
6
- 100.times{ @decoder.peek_1.should == 'a'[0] }
7
- 100.times{ @decoder.peek_2.should == 'ab'.unpack("n").first }
8
- end
9
- end
10
-
11
3
  context "When unpacking from a binary stream" do
12
4
  setup do
13
- @decoder = Erlectricity::Decoder.new(nil)
14
5
  end
15
6
 
16
7
  specify "an erlang atom should decode to a ruby symbol" do
@@ -127,7 +118,6 @@ context "When unpacking from a binary stream" do
127
118
 
128
119
  def get(str)
129
120
  bin = run_erl("term_to_binary(#{str})")
130
- @decoder.in = StringIO.new(bin)
131
- @decoder.read_any
121
+ Erlectricity::Decoder.read_any_from(bin)
132
122
  end
133
123
  end
data/test/encode_spec.rb CHANGED
@@ -88,6 +88,13 @@ context "When packing to a binary stream" do
88
88
  write_any([3] * 512).should == get_erl_with_magic("{#{([3] * 512).join(',')}}")
89
89
  end
90
90
 
91
+ specify "An Erlectricity::List should by default be written as a list" do
92
+ write_any(Erl::List.new([1,2,300])).should == get_erl_with_magic("[1,2,300]")
93
+ write_any(Erl::List.new([300] * 255)).should == get_erl_with_magic("[#{([300] * 255).join(',')}]")
94
+ write_any(Erl::List.new([300] * 256)).should == get_erl_with_magic("[#{([300] * 256).join(',')}]")
95
+ write_any(Erl::List.new([300] * 512)).should == get_erl_with_magic("[#{([300] * 512).join(',')}]")
96
+ end
97
+
91
98
  specify "An array written with write_list should encode as erlang would a list" do
92
99
  get{@encoder.write_list [1,2,300]}.should == get_erl("[1,2,300]")
93
100
  get{@encoder.write_list [300] * 255}.should == get_erl("[#{([300] * 255).join(',')}]")
data/test/matcher_spec.rb CHANGED
@@ -67,7 +67,3 @@ context "a matcher whose matcher is an array" do
67
67
  matcher.matches?(:foo).should == false
68
68
  end
69
69
  end
70
-
71
- context "a matcher" do
72
-
73
- end
@@ -5,8 +5,8 @@ def simple_receiver_and_port(*terms, &block)
5
5
  receiver = if block
6
6
  Erlectricity::Receiver.new(port, &block)
7
7
  else
8
- Erlectricity::Receiver.new(port) do
9
- match(any) do
8
+ Erlectricity::Receiver.new(port) do |f|
9
+ f.when Erl.any do
10
10
  :matched
11
11
  end
12
12
  end
@@ -17,12 +17,12 @@ end
17
17
  context "When a receiver is passed a message that matches two match blocks it" do
18
18
  setup do
19
19
  @port = FakePort.new([:foo, :foo])
20
- @receiver = Erlectricity::Receiver.new(@port) do
21
- match(:foo, :foo) do
20
+ @receiver = Erlectricity::Receiver.new(@port) do |f|
21
+ f.when(:foo, :foo) do
22
22
  :first
23
23
  end
24
24
 
25
- match(:foo, any) do
25
+ f.when(:foo, Erl.any) do
26
26
  :second
27
27
  end
28
28
  end
@@ -41,9 +41,9 @@ context "A receiver" do
41
41
  end
42
42
 
43
43
  specify "should process another message if the matched block returns the results of receive_loop" do
44
- recv = simple_receiver_and_port(:foo, :bar, :baz) do
45
- match(:bar) { }
46
- match(any) { receive_loop }
44
+ recv = simple_receiver_and_port(:foo, :bar, :baz) do |f|
45
+ f.when(:bar) { }
46
+ f.when(Erl.any) { f.receive_loop }
47
47
  end
48
48
 
49
49
  recv.run
@@ -52,15 +52,15 @@ context "A receiver" do
52
52
 
53
53
  specify "should properly nest" do
54
54
  @port = FakePort.new(:foo, :bar, :baz)
55
- @receiver = Erlectricity::Receiver.new(@port) do
56
- match(:foo) do
57
- receive do
58
- match(:bar){ :ok }
55
+ @receiver = Erlectricity::Receiver.new(@port) do |f|
56
+ f.when(:foo) do
57
+ f.receive do |g|
58
+ g.when(:bar){ :ok }
59
59
  end
60
- receive_loop
60
+ f.receive_loop
61
61
  end
62
62
 
63
- match(:baz) do
63
+ f.when(:baz) do
64
64
  :done
65
65
  end
66
66
  end
@@ -71,15 +71,15 @@ context "A receiver" do
71
71
 
72
72
  specify "should queue up skipped results and restore them when a match happens" do
73
73
  @port = FakePort.new(:foo, :baz, :bar)
74
- @receiver = Erlectricity::Receiver.new(@port) do
75
- match(:foo) do
76
- receive do
77
- match(:bar){ :ok }
74
+ @receiver = Erlectricity::Receiver.new(@port) do |f|
75
+ f.when(:foo) do
76
+ f.receive do |g|
77
+ g.when(:bar){ :ok }
78
78
  end
79
- receive_loop
79
+ f.receive_loop
80
80
  end
81
81
 
82
- match(:baz) do
82
+ f.when(:baz) do
83
83
  :done
84
84
  end
85
85
  end
@@ -91,10 +91,10 @@ context "A receiver" do
91
91
  specify "should expose bindings to the matched block" do
92
92
  @port = FakePort.new(:foo, :bar, :baz)
93
93
  results = []
94
- @receiver = Erlectricity::Receiver.new(@port) do
95
- match(atom(:bindinated)) do
94
+ @receiver = Erlectricity::Receiver.new(@port) do |f|
95
+ f.when(Erl.atom) do |bindinated|
96
96
  results << bindinated
97
- receive_loop
97
+ f.receive_loop
98
98
  end
99
99
  end
100
100
 
data/test/test_helper.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+ require 'erlectricity'
2
3
  require 'rubygems'
3
4
  require 'test/unit'
4
5
  require 'test/spec'
5
- require 'erlectricity'
6
6
 
7
7
  class Test::Unit::TestCase
8
8
 
@@ -10,6 +10,11 @@ class Test::Unit::TestCase
10
10
  `erl -noshell -eval 'A = #{code.split.join(' ')}, io:put_chars(A).' -s erlang halt`
11
11
  end
12
12
 
13
+ def encode_packet(code)
14
+ bin = run_erl("term_to_binary(#{code})")
15
+ [bin.length, bin].pack("Na#{bin.length}")
16
+ end
17
+
13
18
  def word_length
14
19
  (1.size * 8) - 2
15
20
  end
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.2
2
+ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: erlectricity
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.0
7
- date: 2007-05-08 00:00:00 -07:00
6
+ version: 0.2.0
7
+ date: 2007-10-29 00:00:00 -07:00
8
8
  summary: A library to interface erlang and ruby through the erlang port system
9
9
  require_paths:
10
10
  - lib
11
+ - ext
11
12
  email: nullstyle@gmail.com
12
13
  homepage: http://erlectricity.rubyforge.org
13
14
  rubyforge_project: erlectricity
@@ -29,6 +30,8 @@ post_install_message:
29
30
  authors:
30
31
  - Scott Fleckenstein
31
32
  files:
33
+ - CONTRIBUTORS
34
+ - History.txt
32
35
  - Manifest.txt
33
36
  - README.txt
34
37
  - Rakefile
@@ -39,6 +42,8 @@ files:
39
42
  - examples/gruff/stat_writer.erl
40
43
  - examples/tinderl/tinderl.erl
41
44
  - examples/tinderl/tinderl.rb
45
+ - ext/decoder.c
46
+ - ext/extconf.rb
42
47
  - lib/erlectricity.rb
43
48
  - lib/erlectricity/condition.rb
44
49
  - lib/erlectricity/conditions/hash.rb
@@ -50,11 +55,11 @@ files:
50
55
  - lib/erlectricity/errors/decode_error.rb
51
56
  - lib/erlectricity/errors/encode_error.rb
52
57
  - lib/erlectricity/errors/erlectricity_error.rb
53
- - lib/erlectricity/match_context.rb
54
58
  - lib/erlectricity/matcher.rb
55
59
  - lib/erlectricity/port.rb
56
60
  - lib/erlectricity/receiver.rb
57
61
  - lib/erlectricity/types/function.rb
62
+ - lib/erlectricity/types/list.rb
58
63
  - lib/erlectricity/types/new_function.rb
59
64
  - lib/erlectricity/types/new_reference.rb
60
65
  - lib/erlectricity/types/pid.rb
@@ -73,10 +78,13 @@ files:
73
78
  test_files:
74
79
  - test/test_erlectricity.rb
75
80
  - test/test_helper.rb
76
- rdoc_options: []
77
-
78
- extra_rdoc_files: []
79
-
81
+ rdoc_options:
82
+ - --main
83
+ - README.txt
84
+ extra_rdoc_files:
85
+ - History.txt
86
+ - Manifest.txt
87
+ - README.txt
80
88
  executables: []
81
89
 
82
90
  extensions: []
@@ -1,20 +0,0 @@
1
- module Erlectricity
2
- class MatchContext
3
- attr_accessor :receiver
4
- def initialize(receiver)
5
- self.receiver = receiver
6
- end
7
-
8
- def receive(&block)
9
- receiver.receive(&block)
10
- end
11
-
12
- def receive_loop
13
- receiver.receive_loop
14
- end
15
-
16
- def send!(*term)
17
- receiver.send!(*term)
18
- end
19
- end
20
- end