comp_tree 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/README +153 -0
  2. data/Rakefile +152 -0
  3. data/comp_tree.gemspec +38 -0
  4. data/contrib/quix/Rakefile +16 -0
  5. data/contrib/quix/install.rb +3 -0
  6. data/contrib/quix/lib/quix/builtin/dir/casefold_brackets.rb +7 -0
  7. data/contrib/quix/lib/quix/builtin/kernel/tap.rb +9 -0
  8. data/contrib/quix/lib/quix/builtin/module/include.rb +21 -0
  9. data/contrib/quix/lib/quix/builtin/module/private.rb +41 -0
  10. data/contrib/quix/lib/quix/config.rb +37 -0
  11. data/contrib/quix/lib/quix/cygwin.rb +60 -0
  12. data/contrib/quix/lib/quix/diagnostic.rb +44 -0
  13. data/contrib/quix/lib/quix/enumerable.rb +33 -0
  14. data/contrib/quix/lib/quix/fileutils.rb +37 -0
  15. data/contrib/quix/lib/quix/hash_struct.rb +27 -0
  16. data/contrib/quix/lib/quix/kernel.rb +61 -0
  17. data/contrib/quix/lib/quix/lazy_struct.rb +55 -0
  18. data/contrib/quix/lib/quix/simple_installer.rb +87 -0
  19. data/contrib/quix/lib/quix/string.rb +38 -0
  20. data/contrib/quix/lib/quix/subpackager.rb +52 -0
  21. data/contrib/quix/lib/quix/thread_local.rb +32 -0
  22. data/contrib/quix/lib/quix/vars.rb +138 -0
  23. data/contrib/quix/lib/quix.rb +32 -0
  24. data/contrib/quix/test/all.rb +12 -0
  25. data/contrib/quix/test/test_deps.rb +25 -0
  26. data/contrib/quix/test/test_include.rb +47 -0
  27. data/contrib/quix/test/test_private.rb +86 -0
  28. data/contrib/quix/test/test_root.rb +19 -0
  29. data/contrib/quix/test/test_struct.rb +48 -0
  30. data/contrib/quix/test/test_vars.rb +187 -0
  31. data/install.rb +3 -0
  32. data/lib/comp_tree/algorithm.rb +210 -0
  33. data/lib/comp_tree/bucket_ipc.rb +151 -0
  34. data/lib/comp_tree/driver.rb +267 -0
  35. data/lib/comp_tree/error.rb +27 -0
  36. data/lib/comp_tree/node.rb +165 -0
  37. data/lib/comp_tree/quix/builtin/kernel/tap.rb +33 -0
  38. data/lib/comp_tree/quix/diagnostic.rb +68 -0
  39. data/lib/comp_tree/quix/kernel.rb +85 -0
  40. data/lib/comp_tree/retriable_fork.rb +42 -0
  41. data/lib/comp_tree/task_node.rb +22 -0
  42. data/lib/comp_tree.rb +23 -0
  43. data/test/all.rb +12 -0
  44. data/test/test_bucketipc.rb +72 -0
  45. data/test/test_circular.rb +36 -0
  46. data/test/test_comp_tree.rb +364 -0
  47. data/test/test_exception.rb +97 -0
  48. metadata +120 -0
@@ -0,0 +1,61 @@
1
+
2
+ require 'thread'
3
+
4
+ module Quix
5
+ module Kernel
6
+ def let
7
+ yield self
8
+ end
9
+
10
+ def singleton_class
11
+ class << self
12
+ self
13
+ end
14
+ end
15
+
16
+ module Gensym
17
+ @mutex = Mutex.new
18
+ @count = 0
19
+
20
+ def gensym(prefix = nil)
21
+ count = Gensym.module_eval {
22
+ @mutex.synchronize {
23
+ @count += 1
24
+ }
25
+ }
26
+ "#{prefix || :G}_#{count}_#{rand}".to_sym
27
+ end
28
+ end
29
+ include Gensym
30
+
31
+ def call_private(method, *args, &block)
32
+ instance_eval { send(method, *args, &block) }
33
+ end
34
+
35
+ def with_warnings(value = true)
36
+ previous = $VERBOSE
37
+ $VERBOSE = value
38
+ begin
39
+ yield
40
+ ensure
41
+ $VERBOSE = previous
42
+ end
43
+ end
44
+
45
+ def no_warnings(&block)
46
+ with_warnings(false, &block)
47
+ end
48
+
49
+ def abort_on_exception(value = true)
50
+ previous = Thread.abort_on_exception
51
+ Thread.abort_on_exception = value
52
+ begin
53
+ yield
54
+ ensure
55
+ Thread.abort_on_exception = previous
56
+ end
57
+ end
58
+
59
+ extend self
60
+ end
61
+ end
@@ -0,0 +1,55 @@
1
+
2
+ require 'ostruct'
3
+ require 'quix/builtin/kernel/tap'
4
+
5
+ module Quix
6
+ #
7
+ # An OpenStruct with the ability to define lazily-evaluated fields.
8
+ #
9
+ class LazyStruct < OpenStruct
10
+ #
11
+ # For mixing into an existing OpenStruct instance singleton class.
12
+ #
13
+ module Mixin
14
+ #
15
+ # &block is evaluated when this attribute is requested. The
16
+ # same result is returned for subsquent calls, until the field
17
+ # is assigned a different value.
18
+ #
19
+ def attribute(reader, &block)
20
+ singleton = (class << self ; self ; end)
21
+ singleton.instance_eval {
22
+ #
23
+ # Define a special reader method in the singleton class.
24
+ #
25
+ define_method(reader) {
26
+ block.call.tap { |value|
27
+ #
28
+ # The value has been computed. Replace this method with a
29
+ # one-liner giving the value.
30
+ #
31
+ singleton.instance_eval {
32
+ remove_method(reader)
33
+ define_method(reader) { value }
34
+ }
35
+ }
36
+ }
37
+
38
+ #
39
+ # Revert to the old OpenStruct behavior when the writer is called.
40
+ #
41
+ writer = "#{reader}=".to_sym
42
+ define_method(writer) { |value|
43
+ singleton.instance_eval {
44
+ remove_method(reader)
45
+ remove_method(writer)
46
+ }
47
+ method_missing(writer, value)
48
+ }
49
+ }
50
+ end
51
+ end
52
+
53
+ include Mixin
54
+ end
55
+ end
@@ -0,0 +1,87 @@
1
+
2
+ require 'rbconfig'
3
+ require 'fileutils'
4
+ require 'find'
5
+ require 'fileutils'
6
+ require 'quix/vars'
7
+
8
+ module Quix
9
+ class SimpleInstaller
10
+ include Quix::Vars
11
+
12
+ def initialize
13
+ dest_root = Config::CONFIG["sitelibdir"]
14
+ sources = []
15
+ Find.find("./lib") { |source|
16
+ if install_file?(source)
17
+ sources << source
18
+ end
19
+ }
20
+ @spec = sources.inject(Array.new) { |acc, source|
21
+ if source == "./lib"
22
+ acc
23
+ else
24
+ dest = File.join(dest_root, source.sub(%r!\A\./lib!, ""))
25
+
26
+ install = lambda {
27
+ if File.directory?(source)
28
+ unless File.directory?(dest)
29
+ puts "mkdir #{dest}"
30
+ FileUtils.mkdir(dest)
31
+ end
32
+ else
33
+ puts "install #{source} --> #{dest}"
34
+ FileUtils.install(source, dest)
35
+ end
36
+ }
37
+
38
+ uninstall = lambda {
39
+ if File.directory?(source)
40
+ if File.directory?(dest)
41
+ puts "rmdir #{dest}"
42
+ FileUtils.rmdir(dest)
43
+ end
44
+ else
45
+ if File.file?(dest)
46
+ puts "rm #{dest}"
47
+ FileUtils.rm(dest)
48
+ end
49
+ end
50
+ }
51
+
52
+ acc << locals_to_hash {%{source, dest, install, uninstall}}
53
+ end
54
+ }
55
+ end
56
+
57
+ def install_file?(source)
58
+ !File.symlink?(source) and
59
+ (File.directory?(source) or
60
+ (File.file?(source) and File.extname(source) == ".rb"))
61
+ end
62
+
63
+ attr_accessor :spec
64
+
65
+ def install
66
+ @spec.each { |entry|
67
+ entry[:install].call
68
+ }
69
+ end
70
+
71
+ def uninstall
72
+ @spec.reverse.each { |entry|
73
+ entry[:uninstall].call
74
+ }
75
+ end
76
+
77
+ def run(args = ARGV)
78
+ if args.empty? or (args.size == 1 and args.first == "install")
79
+ install
80
+ elsif args.size == 1 and args.first == "--uninstall"
81
+ uninstall
82
+ else
83
+ raise "unrecognized arguments: #{args.inspect}"
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,38 @@
1
+
2
+ require 'quix/builtin/kernel/tap'
3
+
4
+ module Quix
5
+ module String
6
+ def trim_left!
7
+ sub!(%r!\A\s+!, "")
8
+ end
9
+
10
+ def trim_right!
11
+ sub!(%r!\s+\Z!, "")
12
+ end
13
+
14
+ def trim!
15
+ result_left = trim_left!
16
+ result_right = trim_right!
17
+ result_left || result_right
18
+ end
19
+
20
+ def trim_left
21
+ clone.tap { |result|
22
+ result.trim_left!
23
+ }
24
+ end
25
+
26
+ def trim_right
27
+ clone.tap { |result|
28
+ result.trim_right!
29
+ }
30
+ end
31
+
32
+ def trim
33
+ clone.tap { |result|
34
+ result.trim!
35
+ }
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,52 @@
1
+
2
+ require 'quix/hash_struct'
3
+
4
+ module Quix
5
+ module Subpackager
6
+ WARNING = %q{
7
+
8
+
9
+ ######################################################
10
+ #
11
+ # **** DO NOT EDIT ****
12
+ #
13
+ # **** THIS IS A GENERATED FILE *****
14
+ #
15
+ ######################################################
16
+
17
+
18
+ }.gsub(%r!^ +!, "")
19
+
20
+ def self.run(packages)
21
+ HashStruct.recursive_new(packages).each_pair { |pkg, pkg_spec|
22
+ pkg_spec.subpackages.each_pair { |subpkg, subpkg_spec|
23
+ process_path = lambda { |path|
24
+ source = "#{subpkg_spec.lib_dir}/#{path}.rb"
25
+ dest = "#{pkg_spec.lib_dir}/#{pkg}/#{path}.rb"
26
+
27
+ contents =
28
+ WARNING +
29
+ File.read(source).gsub(%r!require [\'\"]#{subpkg}!) {
30
+ |match|
31
+ match.sub(%r!#{subpkg}\Z!, "#{pkg}/#{subpkg}")
32
+ }.gsub(subpkg_spec.name_in_ruby) {
33
+ "#{pkg_spec.name_in_ruby}::#{subpkg_spec.name_in_ruby}"
34
+ } +
35
+ WARNING
36
+
37
+ mkdir_p(File.dirname(dest))
38
+ puts "#{source} --> #{dest}"
39
+ File.open(dest, "w") { |t| t.print(contents) }
40
+ }
41
+
42
+ unless subpkg_spec.ignore_root_rb
43
+ process_path.call(subpkg)
44
+ end
45
+ subpkg_spec.sources.each { |path|
46
+ process_path.call("#{subpkg}/#{path}")
47
+ }
48
+ }
49
+ }
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,32 @@
1
+
2
+ require 'thread'
3
+ require 'quix/kernel'
4
+
5
+ module Quix
6
+ class ThreadLocal
7
+ include Quix::Kernel
8
+
9
+ def initialize(prefix = nil, &default)
10
+ @name = gensym(prefix)
11
+ @accessed = gensym(prefix)
12
+ @default = default
13
+ end
14
+
15
+ def value
16
+ t = Thread.current
17
+ unless t[@accessed]
18
+ if @default
19
+ t[@name] = @default.call
20
+ end
21
+ t[@accessed] = true
22
+ end
23
+ t[@name]
24
+ end
25
+
26
+ def value=(value)
27
+ t = Thread.current
28
+ t[@accessed] = true
29
+ t[@name] = value
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,138 @@
1
+
2
+ require 'quix/kernel'
3
+ require 'quix/thread_local'
4
+ require 'quix/builtin/kernel/tap'
5
+ require 'ostruct'
6
+
7
+ module Quix
8
+ module Vars
9
+ include Quix::Kernel
10
+
11
+ def eval_locals(code_with_locals, &block)
12
+ code_with_locals.call.split(",").map { |name|
13
+ # trim
14
+ name.sub(%r!\A\s+!, "").sub(%r!\s+\Z!, "")
15
+ }.each { |name|
16
+ block.call(name, eval(name, code_with_locals.binding))
17
+ }
18
+ end
19
+
20
+ def hash_to_locals(&block)
21
+ if hash = block.call
22
+ hash.each_pair { |name, value|
23
+ Vars.argument_cache.value = value
24
+ eval("#{name} = #{Vars.name}.argument_cache.value", block.binding)
25
+ }
26
+ end
27
+ end
28
+
29
+ def locals_to_hash(&block)
30
+ Hash.new.tap { |hash|
31
+ eval_locals(block) { |name, value|
32
+ hash[name.to_sym] = value
33
+ }
34
+ }
35
+ end
36
+
37
+ def config_to_hash(code)
38
+ Hash.new.tap { |hash|
39
+ each_config_pair(code) { |name, value|
40
+ hash[name] = value
41
+ }
42
+ }
43
+ end
44
+
45
+ def each_config_pair(code, &block)
46
+ Vars.argument_cache.value = code
47
+ vars, bind = private__eval_config_code
48
+ vars.each { |var|
49
+ yield(var.to_sym, eval(var, bind))
50
+ }
51
+ end
52
+
53
+ def hash_to_ivs(opts = nil, &block)
54
+ if hash = block.call
55
+ private__hash_to_ivs(
56
+ hash,
57
+ eval("self", block.binding),
58
+ opts && opts[:force])
59
+ end
60
+ end
61
+
62
+ def locals_to_ivs(opts = nil, &block)
63
+ hash = Hash.new
64
+ eval_locals(block) { |name, value|
65
+ hash[name] = value
66
+ }
67
+ private__hash_to_ivs(
68
+ hash,
69
+ eval("self", block.binding),
70
+ opts && opts[:force])
71
+ end
72
+
73
+ def with_readers(hash, *args, &block)
74
+ caller_self = eval("self", block.binding)
75
+ readers =
76
+ if args.empty?
77
+ hash.keys
78
+ else
79
+ args
80
+ end
81
+ singleton_class.instance_eval {
82
+ added = Array.new
83
+ begin
84
+ readers.each { |reader|
85
+ if caller_self.respond_to?(reader)
86
+ raise(
87
+ "Reader '#{reader}' already exists in #{caller_self.inspect}")
88
+ end
89
+ define_method(reader) {
90
+ hash[reader]
91
+ }
92
+ added << reader
93
+ }
94
+ block.call
95
+ ensure
96
+ added.each { |reader|
97
+ remove_method(reader)
98
+ }
99
+ end
100
+ }
101
+ end
102
+
103
+ private
104
+
105
+ class << self
106
+ attr_accessor :argument_cache
107
+ end
108
+ @argument_cache = ThreadLocal.new
109
+
110
+ def private__eval_config_code
111
+ eval %Q{
112
+ #{Vars.argument_cache.value}
113
+
114
+ [local_variables, binding]
115
+ }
116
+ end
117
+
118
+ def private__hash_to_ivs(hash, target, force)
119
+ target.instance_eval {
120
+ hash.each_pair { |name, value|
121
+ ivar = "@#{name}"
122
+ unless force
123
+ existing_value = no_warnings {
124
+ instance_variable_get(ivar)
125
+ }
126
+ unless existing_value.nil?
127
+ raise "instance variable already set: #{name}"
128
+ end
129
+ end
130
+ instance_variable_set(ivar, value)
131
+ }
132
+ }
133
+ end
134
+
135
+ extend self
136
+ end
137
+ end
138
+
@@ -0,0 +1,32 @@
1
+ #
2
+ # Convience only -- include most everything
3
+ #
4
+
5
+ root = File.dirname(__FILE__)
6
+ pkgname = File.basename(__FILE__).sub(%r!\.rb\Z!, "")
7
+
8
+ Dir["#{root}/#{pkgname}/**/*.rb"].map { |file|
9
+ # change to relative paths
10
+ file.sub(%r!\A#{root}/!, "").sub(%r!\.rb\Z!, "")
11
+ }.reject { |file|
12
+ (file =~ %r!cygwin! and RUBY_PLATFORM !~ %r!cygwin!) or
13
+ file =~ %r!builtin!
14
+ }.each { |file|
15
+ require file
16
+ }
17
+
18
+ require 'quix/builtin/kernel/tap'
19
+
20
+ %w(Config Enumerable FileUtils String).each { |name|
21
+ Kernel.const_get(name).module_eval {
22
+ include Quix.const_get(name)
23
+ }
24
+ }
25
+
26
+ Config.extend(Quix::Config)
27
+
28
+ class Object
29
+ include Quix::Kernel
30
+ end
31
+
32
+ include Quix
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
2
+
3
+ require 'quix/config'
4
+
5
+ #
6
+ # Run in separate exec to check for missing dependencies.
7
+ #
8
+ Dir["#{File.dirname(__FILE__)}/test_*.rb"].each { |test|
9
+ unless system(Quix::Config.ruby_executable, test)
10
+ raise "test failed: #{test}"
11
+ end
12
+ }
@@ -0,0 +1,25 @@
1
+ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
2
+
3
+ require 'test/unit'
4
+ require 'quix/config'
5
+
6
+ class TestDeps < Test::Unit::TestCase
7
+ include Quix::Config
8
+ def test_deps
9
+ ruby = ruby_executable
10
+ root = File.expand_path("#{File.dirname(__FILE__)}/../lib")
11
+ Dir["#{root}/**/*.rb"].map { |file|
12
+ file.
13
+ sub(%r!\A#{root}/!, "").
14
+ sub(%r!\.rb\Z!, "")
15
+ }.each { |file|
16
+ unless file =~ %r!cygwin! and RUBY_PLATFORM !~ %r!cygwin!
17
+ Dir.chdir(root) {
18
+ assert(
19
+ system(ruby, "-r", file, "-e", ""),
20
+ "error requiring: '#{file}'")
21
+ }
22
+ end
23
+ }
24
+ end
25
+ end
@@ -0,0 +1,47 @@
1
+ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
2
+
3
+ require 'test/unit'
4
+ require 'open3'
5
+ require 'quix/config'
6
+
7
+ class TestInclude < Test::Unit::TestCase
8
+ include Quix::Config
9
+
10
+ def test_include
11
+ Dir.chdir(File.dirname(__FILE__)) {
12
+ code = %q{
13
+ $LOAD_PATH.unshift "../lib"
14
+ require 'quix/builtin/module/include'
15
+
16
+ module A
17
+ def f ; end
18
+ end
19
+
20
+ module B
21
+ def f ; end
22
+ end
23
+
24
+ module C
25
+ include A
26
+ include B
27
+ end
28
+
29
+ class D
30
+ include B
31
+ include A
32
+ end
33
+ }
34
+ ruby = ruby_executable
35
+ begin
36
+ stdin, stdout, stderr = Open3.popen3("#{ruby} -d -")
37
+ stdin.puts(code)
38
+ stdin.close_write
39
+ assert_equal(stderr.readlines,
40
+ ["Note: replacing C#f with B#f\n",
41
+ "Note: replacing D#f with A#f\n"])
42
+ rescue NotImplementedError
43
+ puts "Skipping #{File.basename(__FILE__)}."
44
+ end
45
+ }
46
+ end
47
+ end
@@ -0,0 +1,86 @@
1
+ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
2
+
3
+ require 'test/unit'
4
+ require 'quix/config'
5
+ require 'quix/kernel'
6
+
7
+ if Quix::Config.version_ge("1.8.7")
8
+ require 'test/unit'
9
+ require 'quix/builtin/module/private'
10
+
11
+ class TestPrivate < Test::Unit::TestCase
12
+ BODY = %{
13
+ def f ; end
14
+
15
+ private {
16
+ def g ; end
17
+ def h ; end
18
+ }
19
+
20
+ def i ; end
21
+
22
+ private {
23
+ def j ; end
24
+ }
25
+
26
+ def k ; end
27
+
28
+ private {
29
+ }
30
+
31
+ def l ; end
32
+
33
+ def m ; end
34
+ def n ; end
35
+ private :m, :n
36
+
37
+ def o ; end
38
+ }
39
+
40
+ class A
41
+ eval(BODY)
42
+ end
43
+
44
+ module B
45
+ eval(BODY)
46
+ end
47
+
48
+ class C
49
+ include B
50
+ end
51
+
52
+ def test_1
53
+ [A, C].map { |klass| klass.new }.each { |t|
54
+ assert_nothing_raised { t.f }
55
+ assert_raises(NoMethodError) { t.g }
56
+ assert_raises(NoMethodError) { t.h }
57
+ assert_nothing_raised { t.i }
58
+ assert_raises(NoMethodError) { t.j }
59
+ assert_nothing_raised { t.k }
60
+ assert_nothing_raised { t.l }
61
+ assert_raises(NoMethodError) { t.m }
62
+ assert_raises(NoMethodError) { t.n }
63
+ assert_nothing_raised { t.o }
64
+ }
65
+ end
66
+
67
+ def test_2
68
+ added = []
69
+ Class.new {
70
+ extend(Quix::Kernel).singleton_class.instance_eval {
71
+ define_method(:method_added) { |name|
72
+ added << name
73
+ }
74
+ }
75
+
76
+ private {
77
+ def f ; end
78
+ }
79
+
80
+ def g ; end
81
+ }
82
+ assert_equal([:f, :g], added)
83
+ end
84
+ end
85
+ end
86
+
@@ -0,0 +1,19 @@
1
+ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
2
+
3
+ require 'quix'
4
+ require 'test/unit'
5
+
6
+ class TestRoot < Test::Unit::TestCase
7
+ def test_1
8
+ assert_equal(class << self ; self ; end, singleton_class)
9
+ assert_equal("moo", "moo".tap { |t| t*2 })
10
+ assert_equal("moomoo", "moo".let { |t| t*2 })
11
+ assert_equal("zzz", " zzz ".trim)
12
+ assert_nothing_raised {
13
+ ThreadLocal.new
14
+ LazyStruct.new
15
+ HashStruct.new
16
+ Config.ruby_executable
17
+ }
18
+ end
19
+ end