gecoder 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.
Files changed (75) hide show
  1. data/COPYING +17 -0
  2. data/LGPL-LICENSE +458 -0
  3. data/README +20 -0
  4. data/Rakefile +6 -0
  5. data/ext/extconf.rb +29 -0
  6. data/ext/missing.cpp +295 -0
  7. data/ext/missing.h +116 -0
  8. data/ext/vararray.cpp +312 -0
  9. data/ext/vararray.h +146 -0
  10. data/lib/gecoder.rb +4 -0
  11. data/lib/gecoder/bindings.rb +7 -0
  12. data/lib/gecoder/bindings/bindings.rb +2055 -0
  13. data/lib/gecoder/interface.rb +6 -0
  14. data/lib/gecoder/interface/binding_changes.rb +111 -0
  15. data/lib/gecoder/interface/branch.rb +102 -0
  16. data/lib/gecoder/interface/constraints.rb +10 -0
  17. data/lib/gecoder/interface/constraints/distinct.rb +15 -0
  18. data/lib/gecoder/interface/constraints/linear.rb +158 -0
  19. data/lib/gecoder/interface/constraints/relation.rb +76 -0
  20. data/lib/gecoder/interface/enum_wrapper.rb +64 -0
  21. data/lib/gecoder/interface/model.rb +130 -0
  22. data/lib/gecoder/interface/search.rb +23 -0
  23. data/vendor/rust/README +28 -0
  24. data/vendor/rust/bin/cxxgenerator.rb +93 -0
  25. data/vendor/rust/include/rust_checks.hh +115 -0
  26. data/vendor/rust/include/rust_conversions.hh +103 -0
  27. data/vendor/rust/rust.rb +67 -0
  28. data/vendor/rust/rust/attribute.rb +51 -0
  29. data/vendor/rust/rust/bindings.rb +172 -0
  30. data/vendor/rust/rust/class.rb +334 -0
  31. data/vendor/rust/rust/constants.rb +48 -0
  32. data/vendor/rust/rust/container.rb +110 -0
  33. data/vendor/rust/rust/cppifaceparser.rb +129 -0
  34. data/vendor/rust/rust/cwrapper.rb +72 -0
  35. data/vendor/rust/rust/cxxclass.rb +98 -0
  36. data/vendor/rust/rust/element.rb +81 -0
  37. data/vendor/rust/rust/enum.rb +63 -0
  38. data/vendor/rust/rust/function.rb +407 -0
  39. data/vendor/rust/rust/namespace.rb +61 -0
  40. data/vendor/rust/rust/templates/AttributeDefinition.rusttpl +17 -0
  41. data/vendor/rust/rust/templates/AttributeInitBinding.rusttpl +9 -0
  42. data/vendor/rust/rust/templates/BindingsHeader.rusttpl +24 -0
  43. data/vendor/rust/rust/templates/BindingsUnit.rusttpl +46 -0
  44. data/vendor/rust/rust/templates/CWrapperClassDefinitions.rusttpl +64 -0
  45. data/vendor/rust/rust/templates/ClassDeclarations.rusttpl +7 -0
  46. data/vendor/rust/rust/templates/ClassInitialize.rusttpl +6 -0
  47. data/vendor/rust/rust/templates/ConstructorStub.rusttpl +21 -0
  48. data/vendor/rust/rust/templates/CxxClassDefinitions.rusttpl +91 -0
  49. data/vendor/rust/rust/templates/CxxMethodStub.rusttpl +12 -0
  50. data/vendor/rust/rust/templates/CxxStandaloneClassDefinitions.rusttpl +12 -0
  51. data/vendor/rust/rust/templates/EnumDeclarations.rusttpl +3 -0
  52. data/vendor/rust/rust/templates/EnumDefinitions.rusttpl +29 -0
  53. data/vendor/rust/rust/templates/FunctionDefinition.rusttpl +9 -0
  54. data/vendor/rust/rust/templates/FunctionInitAlias.rusttpl +5 -0
  55. data/vendor/rust/rust/templates/FunctionInitBinding.rusttpl +9 -0
  56. data/vendor/rust/rust/templates/MethodInitBinding.rusttpl +9 -0
  57. data/vendor/rust/rust/templates/ModuleDeclarations.rusttpl +3 -0
  58. data/vendor/rust/rust/templates/ModuleDefinitions.rusttpl +3 -0
  59. data/vendor/rust/rust/templates/StandaloneClassDeclarations.rusttpl +5 -0
  60. data/vendor/rust/rust/templates/VariableFunctionCall.rusttpl +14 -0
  61. data/vendor/rust/rust/type.rb +98 -0
  62. data/vendor/rust/test/Makefile +4 -0
  63. data/vendor/rust/test/constants.rb +35 -0
  64. data/vendor/rust/test/cppclass.cc +40 -0
  65. data/vendor/rust/test/cppclass.hh +63 -0
  66. data/vendor/rust/test/cppclass.rb +59 -0
  67. data/vendor/rust/test/cwrapper.c +74 -0
  68. data/vendor/rust/test/cwrapper.h +41 -0
  69. data/vendor/rust/test/cwrapper.rb +56 -0
  70. data/vendor/rust/test/dummyclass.hh +31 -0
  71. data/vendor/rust/test/lib/extension-test.rb +98 -0
  72. data/vendor/rust/test/test-constants.rb +43 -0
  73. data/vendor/rust/test/test-cppclass.rb +82 -0
  74. data/vendor/rust/test/test-cwrapper.rb +77 -0
  75. metadata +144 -0
@@ -0,0 +1,64 @@
1
+ module Gecode
2
+ class Model
3
+ private
4
+
5
+ # Wraps a custom enumerable so that constraints can be specified using it.
6
+ # The argument is altered and returned.
7
+ def wrap_enum(enum)
8
+ unless enum.kind_of? Enumerable
9
+ raise TypeError, 'Only enumerables can be wrapped.'
10
+ end
11
+
12
+ class <<enum
13
+ include Gecode::IntEnumConstraintMethods
14
+ end
15
+ enum.model = self
16
+ return enum
17
+ end
18
+ end
19
+
20
+ # A module containing the methods needed by enumerations containing int
21
+ # variables. Requires that it's included in an enumerable.
22
+ module IntEnumConstraintMethods
23
+ # Specifies that a constraint must hold for the integer variable enum.
24
+ def must
25
+ IntVarEnumConstraintExpression.new(active_space, to_int_var_array)
26
+ end
27
+ alias_method :must_be, :must
28
+
29
+ # Specifies that the negation of a constraint must hold for the integer
30
+ # variable.
31
+ def must_not
32
+ IntVarEnumConstraintExpression.new(active_space, to_int_var_array,
33
+ true)
34
+ end
35
+ alias_method :must_not_be, :must_not
36
+
37
+ # Returns an int variable array with all the bound variables.
38
+ def to_int_var_array
39
+ elements = to_a
40
+ arr = Gecode::Raw::IntVarArray.new(active_space, elements.size)
41
+ elements.each_with_index{ |var, index| arr[index] = var.bind }
42
+ return arr
43
+ end
44
+
45
+ attr_accessor :model
46
+ # Gets the current space of the model the array is connected to.
47
+ def active_space
48
+ @model.active_space
49
+ end
50
+ end
51
+
52
+ # Describes a constraint expression that starts with an enumeration of int
53
+ # variables followed by must or must_not.
54
+ class IntVarEnumConstraintExpression
55
+ # Constructs a new expression with the specified space and int var array
56
+ # with the (bound) variables as source. The expression can optionally be
57
+ # negated.
58
+ def initialize(space, var_array, negate = false)
59
+ @space = space
60
+ @var_array = var_array
61
+ @negate = negate
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,130 @@
1
+ module Gecode
2
+ # Model is the base class that all models must inherit from. The superclass
3
+ # constructor must be called.
4
+ class Model
5
+ # Design notes: Only one model per problem is used. A model has multiple
6
+ # spaces. A model has a base space in which it sets up during the
7
+ # initialization. The model binds the int variables to the current space
8
+ # upon use.
9
+
10
+ # The base from which searches are made.
11
+ attr :base_space
12
+ # The currently active space (the one which variables refer to).
13
+ attr :active_space
14
+
15
+ def initialize
16
+ @active_space = @base_space = Gecode::Raw::Space.new
17
+ end
18
+
19
+ # Creates a new integer variable with the specified domain. The domain can
20
+ # either be a range or a number of elements.
21
+ def int_var(*domain_args)
22
+ range = domain_range(*domain_args)
23
+ index = active_space.new_int_vars(range.begin, range.end).first
24
+ construct_int_var(index, *domain_args)
25
+ end
26
+
27
+ # Creates an array containing the specified number of integer variables
28
+ # with the specified domain. The domain can either be a range or a number
29
+ # of elements.
30
+ def int_var_array(count, *domain_args)
31
+ # TODO: Maybe the custom domain should be specified as an array instead?
32
+
33
+ range = domain_range(*domain_args)
34
+ variables = []
35
+ active_space.new_int_vars(range.begin, range.end, count).each do |index|
36
+ variables << construct_int_var(index, *domain_args)
37
+ end
38
+ return wrap_enum(variables)
39
+ end
40
+
41
+ private
42
+
43
+ # Returns the range of the specified domain arguments, which can either be
44
+ # given as a range or a number of elements. Raises ArgumentError if no
45
+ # arguments have been specified.
46
+ def domain_range(*domain_args)
47
+ min = max = nil
48
+ if domain_args.empty?
49
+ raise ArgumentError, 'A domain has to be specified.'
50
+ elsif domain_args.size > 1
51
+ min = domain_args.min
52
+ max = domain_args.max
53
+ else
54
+ element = domain_args.first
55
+ if element.respond_to? :begin and element.respond_to? :end
56
+ min = element.begin
57
+ max = element.end
58
+ else
59
+ min = max = element
60
+ end
61
+ end
62
+ return min..max
63
+ end
64
+
65
+ # Creates an integer variable from the specified index and domain. The
66
+ # domain can either be given as a range or as a number of elements.
67
+ def construct_int_var(index, *domain_args)
68
+ var = FreeIntVar.new(self, index)
69
+
70
+ if domain_args.size > 1
71
+ # Place an additional domain constraint on the variable with the
72
+ # arguments as domain.
73
+ # TODO: use the model's way of defining domain constraints when
74
+ # available.
75
+ domain_set = Gecode::Raw::IntSet.new(domain_args, domain_args.size)
76
+ Gecode::Raw::dom(active_space, var.bind, domain_set,
77
+ Gecode::Raw::ICL_DEF)
78
+ end
79
+ return var
80
+ end
81
+ end
82
+
83
+ # An IntVar that is bound to a model, but not to a particular space.
84
+ class FreeIntVar
85
+ attr_accessor :model
86
+
87
+ # Creates an int variable with the specified index.
88
+ def initialize(model, index)
89
+ @model = model
90
+ @index = index
91
+ @bound_space = @bound_var = nil
92
+ end
93
+
94
+ # Delegate methods we can't handle to the bound int variable if possible.
95
+ def method_missing(name, *args)
96
+ if Gecode::Raw::IntVar.instance_methods.include? name.to_s
97
+ bind.send(name, *args)
98
+ else
99
+ super
100
+ end
101
+ end
102
+
103
+ # Binds the int variable to the currently active space of the model,
104
+ # returning the bound int variable.
105
+ def bind
106
+ space = active_space
107
+ unless @bound_space == space
108
+ # We have not bound the variable to this space, so we do it now.
109
+ @bound = space.int_var(@index)
110
+ @bound_space = space
111
+ end
112
+ return @bound
113
+ end
114
+
115
+ def inspect
116
+ if assigned?
117
+ "#<FreeIntVar range: val.to_s>"
118
+ else
119
+ "#<FreeIntVar range: #{min}..#{max}>"
120
+ end
121
+ end
122
+
123
+ private
124
+
125
+ # Returns the space that the int variable should bind to when needed.
126
+ def active_space
127
+ @model.active_space
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,23 @@
1
+ module Gecode
2
+ class Model
3
+ private
4
+
5
+ # Used during the search.
6
+ COPY_DIST = 16
7
+ ADAPTATION_DIST = 4
8
+
9
+ public
10
+
11
+ # Finds the first solution to the modelled problem and updates the variables
12
+ # to that solution. Returns the model if a solution was found, nil
13
+ # otherwise.
14
+ def solve!
15
+ stop = Gecode::Raw::Search::Stop.new
16
+ dfs = Gecode::Raw::DFS.new(@base_space, COPY_DIST, ADAPTATION_DIST, stop)
17
+ space = dfs.next
18
+ return nil if space.nil?
19
+ @active_space = space
20
+ return self
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ When I wanted to write a GUI tagger for KDE using Korundum (KDE Ruby
2
+ bindings), I discovered to my sadness that most of the tagging
3
+ extensions for Ruby were simple bindings for the C interface of the
4
+ most common TagLib library (that is written in C++ instead); writing
5
+ bindings for the C++ interface was quite a complex task, and boring as
6
+ it was to copy and paste the same code over and over.
7
+
8
+ For this reason I started first writing a simple extensions generator
9
+ that used a YAML description of the namespaces and the classes to
10
+ write bindings for. This method worked fine for what I was working on
11
+ (RubyTag++), and also allowed me to write quite quickly some Ruby
12
+ bindings for Hunspell too.
13
+
14
+ Unfortunately this generator was not adaptable enough to write
15
+ bindings for C libraries that used some object oriented interfaces,
16
+ and was a mess to extend to provide bindings more suitable to some
17
+ different cases than the ones I've already used the script for.
18
+
19
+ For this reason I've started working on Rust: a more flexible
20
+ extensions builder, that allowed to bind even C libraries by faking
21
+ some classes on Ruby (although I haven't implemented this yet).
22
+
23
+ Hopefully in the future Rust can be used to easily produce Ruby
24
+ bindings for a number of libraries that currently aren't available at
25
+ all.
26
+
27
+ To contact me, send me patches or comments, just write to
28
+ <flameeyes@gmail.com> .
@@ -0,0 +1,93 @@
1
+
2
+ require 'rust/cppifaceparser'
3
+
4
+
5
+ if __FILE__ == $0
6
+ def usage
7
+ puts "Use: #{File.basename($0)} [header] [module name] [output file]"
8
+ end
9
+
10
+ parser = Rust::Cpp::IfaceParser.new
11
+
12
+ if ARGV.size != 3 or not File.exists?(ARGV[0].to_s)
13
+ usage
14
+ exit 0
15
+ end
16
+
17
+ header = ARGV[0]
18
+ namespace = ARGV[1]
19
+ outputfile = ARGV[2]
20
+ outputfile += ".rb" if not outputfile =~ /\.rb$/
21
+
22
+ classes = parser.parseFile(header)
23
+
24
+ rust = %@
25
+ require 'rust'
26
+
27
+ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "#{namespace}" do |b|
28
+ b.include_header '#{header}', Rust::Bindings::HeaderGlobal
29
+ b.add_namespace "#{namespace}", "" do |ns|
30
+ @
31
+ classes.each { |klass|
32
+ rust += %@ ns.add_cxx_class "#{klass[:name]}" do |klass|\n@
33
+ klass[:constructors].each { |constructor|
34
+ rust += " klass.add_constructor "
35
+ if not constructor[:params].empty? and not constructor[:params].detect { |p| p[:type] =~ /void/ }
36
+ rust += "do |method|\n"
37
+ constructor[:params].each { |param|
38
+ rust += %@ method.add_parameter "#{param[:type]}", "#{param[:name]}"\n@
39
+ }
40
+ rust += " end"
41
+ end
42
+ rust += "\n"
43
+ }
44
+
45
+ klass[:methods].each { |method|
46
+ comment_method = false
47
+ if method[:params].detect { |p| p[:type] =~ /\s*\*\s*\*/ }
48
+ $stderr << "Ignoring method: #{method[:name]}\n"
49
+ comment_method = true
50
+ end
51
+
52
+ rust += "# " if comment_method
53
+ rust += %@ klass.add_method "#{method[:name]}", "#{method[:type]}"@
54
+ if not method[:params].empty? and not method[:params].detect { |p| p[:type] =~ /void/ }
55
+ rust += " do |method|\n" if not method[:params].empty?
56
+
57
+
58
+ method[:params].each { |param|
59
+ rust += "# " if comment_method
60
+ rust += %@ method.add_parameter "#{param[:type]}", "#{param[:name]}"\n@
61
+ }
62
+ rust += "# " if comment_method
63
+ rust += " end"
64
+ end
65
+
66
+ rust += "\n"
67
+ }
68
+ rust += " end\n"
69
+ }
70
+
71
+ rust += %@
72
+ end
73
+ end
74
+ @
75
+
76
+ File.open( outputfile, "w" ) { |f|
77
+ f << rust << "\n"
78
+ }
79
+
80
+ # Create configure.rb
81
+ File.open( File.dirname(outputfile)+"/configure.rb", "w" ) { |f|
82
+ f << %@
83
+ require 'mkmf'
84
+ find_header("rust_conversions.hh", "./include" )
85
+ eval File.open("#{File.basename(outputfile)}").readlines.to_s
86
+ create_makefile("#{namespace}")
87
+ @
88
+ }
89
+
90
+ end
91
+
92
+
93
+
@@ -0,0 +1,115 @@
1
+ /* Copyright (c) 2007 David Cuadrado <krawek@gmail.com>
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining
4
+ * a copy of this software and associated documentation files (the
5
+ * "Software"), to deal in the Software without restriction, including
6
+ * without limitation the rights to use, copy, modify, merge,
7
+ * publish, distribute, sublicense, and/or sell copies of the Software,
8
+ * and to permit persons to whom the Software is furnished to do so,
9
+ * subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be
12
+ * included in all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
18
+ * BE LIABLE
19
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ */
23
+
24
+ #ifndef __RUST_CHECKS__
25
+ #define __RUST_CHECKS__
26
+
27
+ #include <ruby.h>
28
+
29
+ static inline void rust_CheckType(VALUE *a)
30
+ {
31
+ Check_Type(a[0], NUM2INT(a[1]));
32
+ }
33
+
34
+ static inline bool isType(VALUE val, int type)
35
+ {
36
+ int result;
37
+ if( type == 0x0 ) return false;
38
+
39
+ VALUE args[2];
40
+ args[0] = (VALUE)val;
41
+ args[1] = INT2FIX(type);
42
+
43
+ rb_protect( (VALUE(*)(VALUE))rust_CheckType, (VALUE)args, &result);
44
+ return result == 0;
45
+ }
46
+
47
+
48
+ static inline bool is_object(VALUE val)
49
+ {
50
+ return isType(val, T_OBJECT);
51
+ }
52
+
53
+ static inline bool is_class(VALUE val)
54
+ {
55
+ return isType(val, T_CLASS);
56
+ }
57
+
58
+ static inline bool is_module(VALUE val)
59
+ {
60
+ return isType(val, T_MODULE);
61
+ }
62
+
63
+ static inline bool is_fLoat(VALUE val)
64
+ {
65
+ return isType(val, T_FLOAT);
66
+ }
67
+
68
+ static inline bool is_string(VALUE val)
69
+ {
70
+ return isType(val, T_STRING);
71
+ }
72
+
73
+ static inline bool is_regexp(VALUE val)
74
+ {
75
+ return isType(val, T_REGEXP);
76
+ }
77
+
78
+ static inline bool is_array(VALUE val)
79
+ {
80
+ return isType(val, T_ARRAY);
81
+ }
82
+
83
+ static inline bool is_int(VALUE val)
84
+ {
85
+ return isType(val, T_FIXNUM);
86
+ }
87
+
88
+ static inline bool is_hash(VALUE val)
89
+ {
90
+ return isType(val, T_HASH);
91
+ }
92
+
93
+ static inline bool is_symbol(VALUE val)
94
+ {
95
+ return isType(val, T_SYMBOL);
96
+ }
97
+
98
+ static inline bool is_bool(VALUE val)
99
+ {
100
+ return val == Qtrue || val == Qfalse;
101
+ }
102
+
103
+ static inline bool is_charPtr(VALUE val)
104
+ {
105
+ char *c = 0;
106
+ c = reinterpret_cast<char *>(DATA_PTR(val));
107
+
108
+ return c != 0; // FIXME
109
+ }
110
+
111
+
112
+
113
+
114
+ #endif
115
+