erlectricity 0.1.0 → 0.2.0

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.
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