dataflow 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +25 -0
- data/README.textile +19 -0
- data/Rakefile +1 -1
- data/dataflow.rb +10 -8
- data/{lib → dataflow}/actor.rb +0 -0
- data/dataflow/equality.rb +28 -0
- data/{lib → dataflow}/port.rb +0 -0
- data/spec/actor_spec.rb +0 -1
- data/spec/by_need_spec.rb +50 -7
- data/spec/equality_spec.rb +40 -0
- data/spec/inspect_spec.rb +19 -0
- data/spec/spec_helper.rb +4 -1
- metadata +18 -15
- data/History.txt +0 -12
data/HISTORY
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
== 0.2.0 / 2009-07-09
|
2
|
+
|
3
|
+
* Major enhancements
|
4
|
+
|
5
|
+
* Made equality between objects and dataflow variables more transparent
|
6
|
+
(load equality changes with: require 'dataflow/equality')
|
7
|
+
|
8
|
+
* Minor enhancements
|
9
|
+
|
10
|
+
* Made #inspect work with unbound variables to not crash deubggers/repls/etc
|
11
|
+
|
12
|
+
* Made relationship between lazy and dataflow behavior more strict
|
13
|
+
|
14
|
+
== 0.1.1 / 2009-06-13
|
15
|
+
|
16
|
+
* Minor enhancements
|
17
|
+
|
18
|
+
* Got the "require_path" set correctly so rubygems can be used =)
|
19
|
+
|
20
|
+
|
21
|
+
== 0.1.0 / 2009-06-13
|
22
|
+
|
23
|
+
* 1 major enhancement
|
24
|
+
|
25
|
+
* Birthday!
|
data/README.textile
CHANGED
@@ -34,6 +34,15 @@ side-effects. Use regular Ruby threading to create threads, use
|
|
34
34
|
"local" or "declare" to create new variables, and use "unify" to bind
|
35
35
|
variables.
|
36
36
|
|
37
|
+
h1. Install
|
38
|
+
|
39
|
+
To install the latest release as a gem:
|
40
|
+
<pre>sudo gem install dataflow</pre>
|
41
|
+
|
42
|
+
h1. IRC
|
43
|
+
|
44
|
+
<pre>#dataflow-gem @ freenode.net</pre>
|
45
|
+
|
37
46
|
h1. Examples
|
38
47
|
|
39
48
|
<pre>
|
@@ -160,6 +169,16 @@ Ping.join
|
|
160
169
|
Pong.join
|
161
170
|
</pre>
|
162
171
|
|
172
|
+
h1. Equality
|
173
|
+
|
174
|
+
Most Ruby implmentations will not use method calls for equality
|
175
|
+
operations in base types/classes. This means equality between dataflow
|
176
|
+
variables and those base types will not behave as expected. Require
|
177
|
+
the following to get equality on base types that uses method calls,
|
178
|
+
while still passing rubyspec:
|
179
|
+
|
180
|
+
<pre>require "dataflow/equality"</pre>
|
181
|
+
|
163
182
|
h1. References
|
164
183
|
|
165
184
|
The basis of dataflow variables around a language is not common among
|
data/Rakefile
CHANGED
@@ -20,7 +20,7 @@ spec = Gem::Specification.new do |s|
|
|
20
20
|
s.homepage = "http://github.com/larrytheliquid/dataflow"
|
21
21
|
s.summary = "Dataflow concurrency for Ruby (inspired by the Oz language)"
|
22
22
|
s.description = s.summary
|
23
|
-
s.files = %w[LICENSE
|
23
|
+
s.files = %w[LICENSE HISTORY Rakefile README.textile dataflow.rb] + Dir["dataflow/**/*"] + Dir["examples/**/*"]
|
24
24
|
s.require_path = '.'
|
25
25
|
s.test_files = Dir["spec/**/*"]
|
26
26
|
end
|
data/dataflow.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'monitor'
|
2
2
|
|
3
3
|
module Dataflow
|
4
|
-
VERSION = "0.
|
4
|
+
VERSION = "0.2.0"
|
5
5
|
|
6
6
|
def self.included(cls)
|
7
7
|
class << cls
|
@@ -42,22 +42,23 @@ module Dataflow
|
|
42
42
|
# initialized instance variables in get/set methods for memory and
|
43
43
|
# performance reasons
|
44
44
|
class Variable
|
45
|
-
instance_methods.each { |m| undef_method m
|
45
|
+
instance_methods.each { |m| undef_method m }
|
46
46
|
LOCK = Monitor.new
|
47
47
|
def initialize(&block) @__trigger__ = block if block_given? end
|
48
48
|
|
49
49
|
# Lazy-load conditions to be nice on memory usage
|
50
50
|
def __binding_condition__() @__binding_condition__ ||= LOCK.new_cond end
|
51
|
-
|
51
|
+
|
52
52
|
def __unify__(value)
|
53
53
|
LOCK.synchronize do
|
54
|
+
__activate_trigger__ if @__trigger__
|
54
55
|
if @__bound__
|
55
|
-
raise UnificationError if
|
56
|
+
raise UnificationError if self != value
|
56
57
|
else
|
57
58
|
@__value__ = value
|
58
59
|
@__bound__ = true
|
59
60
|
__binding_condition__.broadcast # wakeup all method callers
|
60
|
-
|
61
|
+
@__binding_condition__ = nil # GC
|
61
62
|
end
|
62
63
|
end
|
63
64
|
@__value__
|
@@ -66,12 +67,13 @@ module Dataflow
|
|
66
67
|
def __activate_trigger__
|
67
68
|
@__value__ = @__trigger__.call
|
68
69
|
@__bound__ = true
|
69
|
-
|
70
|
+
@__trigger__ = nil # GC
|
70
71
|
end
|
71
72
|
|
72
73
|
def method_missing(name, *args, &block)
|
73
74
|
LOCK.synchronize do
|
74
75
|
unless @__bound__
|
76
|
+
return '#<Dataflow::Variable unbound>' if name == :inspect
|
75
77
|
if @__trigger__
|
76
78
|
__activate_trigger__
|
77
79
|
else
|
@@ -86,5 +88,5 @@ module Dataflow
|
|
86
88
|
UnificationError = Class.new StandardError
|
87
89
|
end
|
88
90
|
|
89
|
-
require "#{File.dirname(__FILE__)}/
|
90
|
-
require "#{File.dirname(__FILE__)}/
|
91
|
+
require "#{File.dirname(__FILE__)}/dataflow/port"
|
92
|
+
require "#{File.dirname(__FILE__)}/dataflow/actor"
|
data/{lib → dataflow}/actor.rb
RENAMED
File without changes
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# The purpose of this file is to make equality use method calls in as
|
2
|
+
# many Ruby implementations as possible. If method calls are used,
|
3
|
+
# then equality operations using dataflow variaables becomes seemless
|
4
|
+
# I realize overriding core classes is a pretty nasty hack, but if you
|
5
|
+
# have a better idea that also passes the equality_specs then I'm all
|
6
|
+
# ears. Please run the rubyspec before committing changes to this file.
|
7
|
+
|
8
|
+
class Object
|
9
|
+
def ==(other)
|
10
|
+
__id__ == other.__id__
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Symbol
|
15
|
+
def ==(other)
|
16
|
+
__id__ == other.__id__
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Regexp
|
21
|
+
def ==(other)
|
22
|
+
other.is_a?(Regexp) &&
|
23
|
+
casefold? == other.casefold? &&
|
24
|
+
kcode == other.kcode &&
|
25
|
+
options == other.options &&
|
26
|
+
source == other.source
|
27
|
+
end
|
28
|
+
end
|
data/{lib → dataflow}/port.rb
RENAMED
File without changes
|
data/spec/actor_spec.rb
CHANGED
data/spec/by_need_spec.rb
CHANGED
@@ -1,12 +1,55 @@
|
|
1
1
|
require "#{File.dirname(__FILE__)}/spec_helper"
|
2
2
|
|
3
|
-
describe 'A by_need
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
describe 'A by_need expression' do
|
4
|
+
describe 'when a method is called on it' do
|
5
|
+
it 'binds its variable' do
|
6
|
+
local do |x, y, z|
|
7
|
+
Thread.new { unify y, by_need { 4 } }
|
8
|
+
Thread.new { unify z, x + y }
|
9
|
+
Thread.new { unify x, by_need { 3 } }
|
10
|
+
z.should == 7
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'when a bound variable is unified to it' do
|
16
|
+
it 'passes unififcation for equal values' do
|
17
|
+
local do |x|
|
18
|
+
unify x, by_need { 1 }
|
19
|
+
unify x, 1
|
20
|
+
x.should == 1
|
21
|
+
|
22
|
+
y = by_need { 1 }
|
23
|
+
unify y, 1
|
24
|
+
y.should == 1
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'fails unififcation for unequal values' do
|
29
|
+
local do |x|
|
30
|
+
unify x, by_need { 1 }
|
31
|
+
lambda { unify x, 2 }.should raise_error(Dataflow::UnificationError)
|
32
|
+
|
33
|
+
y = by_need { 1 }
|
34
|
+
lambda { unify y, 2 }.should raise_error(Dataflow::UnificationError)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'when it is unified to a bound variable' do
|
39
|
+
it 'passes unififcation for equal values' do
|
40
|
+
local do |x|
|
41
|
+
unify x, 1
|
42
|
+
unify x, by_need { 1 }
|
43
|
+
x.should == 1
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'fails unification for unequal values' do
|
48
|
+
local do |x|
|
49
|
+
unify x, 1
|
50
|
+
lambda { unify x, by_need { 2 } }.should raise_error(Dataflow::UnificationError)
|
51
|
+
end
|
52
|
+
end
|
10
53
|
end
|
11
54
|
end
|
12
55
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/spec_helper"
|
2
|
+
|
3
|
+
describe 'Unifying a bound value' do
|
4
|
+
[nil, true, false,
|
5
|
+
:sym, "str", /regex/,
|
6
|
+
3, 2.0,
|
7
|
+
Object.new, Class.new.new,
|
8
|
+
[], {}].each do |type|
|
9
|
+
describe "for #{type.class} instances" do
|
10
|
+
it 'passes unification for an object of equal value' do
|
11
|
+
local do |var, var2|
|
12
|
+
unify var, type
|
13
|
+
var.should == type
|
14
|
+
type.should == var
|
15
|
+
lambda {unify var, type}.should_not raise_error
|
16
|
+
|
17
|
+
unify var2, type
|
18
|
+
var.should == var2
|
19
|
+
var2.should == var
|
20
|
+
lambda {unify var, var2}.should_not raise_error
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'fails unification for an object of inequal value' do
|
25
|
+
different = Object.new
|
26
|
+
local do |var, var2|
|
27
|
+
unify var, type
|
28
|
+
var.should_not == different
|
29
|
+
different.should_not == var
|
30
|
+
lambda {unify var, different}.should raise_error(Dataflow::UnificationError)
|
31
|
+
|
32
|
+
unify var2, different
|
33
|
+
var.should_not == var2
|
34
|
+
var2.should_not == var
|
35
|
+
lambda {unify var, different}.should raise_error(Dataflow::UnificationError)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/spec_helper"
|
2
|
+
|
3
|
+
describe "An unbound variable" do
|
4
|
+
it "should be inspectable for debugging purposes" do
|
5
|
+
local do |unbound|
|
6
|
+
unbound.inspect.should == "#<Dataflow::Variable unbound>"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "An bound variable" do
|
12
|
+
it "should proxy inspect" do
|
13
|
+
local do |bound|
|
14
|
+
bound.inspect
|
15
|
+
unify bound, "str"
|
16
|
+
bound.should == "str"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'spec'
|
3
|
-
require
|
3
|
+
require "#{File.dirname(__FILE__)}/../dataflow"
|
4
|
+
require "#{File.dirname(__FILE__)}/../dataflow/equality"
|
5
|
+
|
6
|
+
Thread.abort_on_exception = true
|
4
7
|
|
5
8
|
Spec::Runner.configure do |config|
|
6
9
|
config.include Dataflow
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dataflow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Larry Diehl
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-07-09 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -23,22 +23,23 @@ extra_rdoc_files: []
|
|
23
23
|
|
24
24
|
files:
|
25
25
|
- LICENSE
|
26
|
-
-
|
26
|
+
- HISTORY
|
27
27
|
- Rakefile
|
28
28
|
- README.textile
|
29
29
|
- dataflow.rb
|
30
|
-
-
|
31
|
-
-
|
32
|
-
-
|
30
|
+
- dataflow/actor.rb
|
31
|
+
- dataflow/equality.rb
|
32
|
+
- dataflow/port.rb
|
33
|
+
- examples/data_driven.rb
|
33
34
|
- examples/dataflow_http_gets.rb
|
35
|
+
- examples/future_http_gets.rb
|
34
36
|
- examples/instance_variables.rb
|
35
|
-
- examples/data_driven.rb
|
36
|
-
- examples/ring.rb
|
37
|
-
- examples/port_send.rb
|
38
37
|
- examples/laziness.rb
|
39
|
-
- examples/
|
40
|
-
- examples/future_http_gets.rb
|
38
|
+
- examples/local_variables.rb
|
41
39
|
- examples/messages.rb
|
40
|
+
- examples/port_http_gets.rb
|
41
|
+
- examples/port_send.rb
|
42
|
+
- examples/ring.rb
|
42
43
|
has_rdoc: false
|
43
44
|
homepage: http://github.com/larrytheliquid/dataflow
|
44
45
|
post_install_message:
|
@@ -66,10 +67,12 @@ signing_key:
|
|
66
67
|
specification_version: 2
|
67
68
|
summary: Dataflow concurrency for Ruby (inspired by the Oz language)
|
68
69
|
test_files:
|
69
|
-
- spec/
|
70
|
+
- spec/actor_spec.rb
|
70
71
|
- spec/by_need_spec.rb
|
71
|
-
- spec/
|
72
|
+
- spec/dataflow_spec.rb
|
73
|
+
- spec/equality_spec.rb
|
74
|
+
- spec/inspect_spec.rb
|
75
|
+
- spec/need_later_spec.rb
|
72
76
|
- spec/port_spec.rb
|
73
77
|
- spec/spec.opts
|
74
|
-
- spec/
|
75
|
-
- spec/actor_spec.rb
|
78
|
+
- spec/spec_helper.rb
|