Class: Rbind::GeneratorRuby
- Inherits:
-
Object
- Object
- Rbind::GeneratorRuby
- Includes:
- Hooks
- Defined in:
- lib/rbind/generator_ruby.rb
Defined Under Namespace
Classes: HelperBase, RBindHelper, RTypeHelper, RTypeTemplateHelper
Class Attribute Summary collapse
-
.ffi_type_map ⇒ Object
Returns the value of attribute ffi_type_map.
-
.on_normalize_type_name(&block) ⇒ Object
Returns the value of attribute on_normalize_type_name.
-
.ruby_default_value_map ⇒ Object
Returns the value of attribute ruby_default_value_map.
Instance Attribute Summary collapse
-
#compact_namespace ⇒ Object
Returns the value of attribute compact_namespace.
-
#file_prefix ⇒ Object
Returns the value of attribute file_prefix.
-
#library_name ⇒ Object
Returns the value of attribute library_name.
-
#module_name ⇒ Object
Returns the value of attribute module_name.
-
#output_path ⇒ Object
Returns the value of attribute output_path.
-
#required_module_names ⇒ Object
Returns the value of attribute required_module_names.
-
#root ⇒ Object
readonly
Returns the value of attribute root.
Class Method Summary collapse
- .keyword?(name) ⇒ Boolean
- .normalize_alias_method_name(orig_name) ⇒ Object
- .normalize_arg_name(name) ⇒ Object
- .normalize_basic_type_name_ffi(name) ⇒ Object
- .normalize_default_value(parameter) ⇒ Object
- .normalize_doc(str) ⇒ Object
- .normalize_enum_name(name) ⇒ Object
-
.normalize_method_name(orig_name) ⇒ Object
normalize c method to meet ruby conventions see unit tests.
- .normalize_type_name(name) ⇒ Object
Instance Method Summary collapse
- #generate(path = @output_path) ⇒ Object
-
#initialize(root, module_name = "Rbind", library_name = "rbind_lib") ⇒ GeneratorRuby
constructor
A new instance of GeneratorRuby.
Constructor Details
#initialize(root, module_name = "Rbind", library_name = "rbind_lib") ⇒ GeneratorRuby
Returns a new instance of GeneratorRuby.
794 795 796 797 798 799 800 |
# File 'lib/rbind/generator_ruby.rb', line 794 def initialize(root,module_name ="Rbind",library_name="rbind_lib") @root = root @rbind_wrapper = ERB.new(File.open(File.join(File.dirname(__FILE__),"templates","ruby","rbind.rb")).read,nil,"-") @module_name = module_name @library_name = library_name @compact_namespace = true end |
Class Attribute Details
.ffi_type_map ⇒ Object
Returns the value of attribute ffi_type_map.
14 15 16 |
# File 'lib/rbind/generator_ruby.rb', line 14 def ffi_type_map @ffi_type_map end |
.on_normalize_type_name(&block) ⇒ Object
Returns the value of attribute on_normalize_type_name.
13 14 15 |
# File 'lib/rbind/generator_ruby.rb', line 13 def on_normalize_type_name @on_normalize_type_name end |
.ruby_default_value_map ⇒ Object
Returns the value of attribute ruby_default_value_map.
12 13 14 |
# File 'lib/rbind/generator_ruby.rb', line 12 def ruby_default_value_map @ruby_default_value_map end |
Instance Attribute Details
#compact_namespace ⇒ Object
Returns the value of attribute compact_namespace.
787 788 789 |
# File 'lib/rbind/generator_ruby.rb', line 787 def compact_namespace @compact_namespace end |
#file_prefix ⇒ Object
Returns the value of attribute file_prefix.
786 787 788 |
# File 'lib/rbind/generator_ruby.rb', line 786 def file_prefix @file_prefix end |
#library_name ⇒ Object
Returns the value of attribute library_name.
784 785 786 |
# File 'lib/rbind/generator_ruby.rb', line 784 def library_name @library_name end |
#module_name ⇒ Object
Returns the value of attribute module_name.
782 783 784 |
# File 'lib/rbind/generator_ruby.rb', line 782 def module_name @module_name end |
#output_path ⇒ Object
Returns the value of attribute output_path.
785 786 787 |
# File 'lib/rbind/generator_ruby.rb', line 785 def output_path @output_path end |
#required_module_names ⇒ Object
Returns the value of attribute required_module_names.
783 784 785 |
# File 'lib/rbind/generator_ruby.rb', line 783 def required_module_names @required_module_names end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
788 789 790 |
# File 'lib/rbind/generator_ruby.rb', line 788 def root @root end |
Class Method Details
.keyword?(name) ⇒ Boolean
20 21 22 |
# File 'lib/rbind/generator_ruby.rb', line 20 def self.keyword?(name) %w{__FILE__ __LINE__ alias and begin BEGIN break case class def defined? do else elsif end END ensure false for if in module next nil not or redo rescue retry return self super then true undef unless until when while yield}.include? name end |
.normalize_alias_method_name(orig_name) ⇒ Object
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/rbind/generator_ruby.rb', line 183 def self.normalize_alias_method_name(orig_name) name = orig_name #replace operatorX with the correct ruby operator when #there are overloaded operators name = if name =~/^operator(.*)/ n = $1 if n =~ /\(\)/ raise "forbbiden method name #{name}" elsif n =~ /(.*)(\d)/ # check for overloaded operators and use alias name for them alias_name = RNamespace.default_operator_alias[$1] if not alias_name raise ArgumentError, "Normalization failed. Operator: #{$1} unknown" end "#{alias_name}_operator#{$2}" else # this operators does not exist if n == "++" || n == "--" alias_name = RNamespace.default_operator_alias[n] if not alias_name raise ArgumentError, "Normalization failed. Operator: #{$1} unknown" end "#{alias_name}_operator" else # we can use the c++ name n end end else name end end |
.normalize_arg_name(name) ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/rbind/generator_ruby.rb', line 38 def self.normalize_arg_name(name) name = name.to_s.sub(/\A#{RBase.cprefix}?/, "").gsub(/(?<!\A)\p{Lu}/u, '_\0').downcase name = if keyword?(name) "#{name}_" else name end # check for digits at the beginning if name =~/\d(.*)/ "_#{name}" else name end end |
.normalize_basic_type_name_ffi(name) ⇒ Object
173 174 175 176 177 178 179 180 181 |
# File 'lib/rbind/generator_ruby.rb', line 173 def self.normalize_basic_type_name_ffi(name) n = ffi_type_map[name] n ||= name if n =~ /\*/ "pointer" else n end end |
.normalize_default_value(parameter) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/rbind/generator_ruby.rb', line 53 def self.normalize_default_value(parameter) return nil unless parameter.default_value if self.callbacks_for_hook(:on_normalize_default_value) results = self.run_hook(:on_normalize_default_value,parameter) results.compact! return results.first unless results.empty? end val = if parameter.type.basic_type? || parameter.type.ptr? if ruby_default_value_map.has_key?(parameter.default_value) ruby_default_value_map[parameter.default_value] elsif parameter.type.name == "float" parameter.default_value.gsub("f","") elsif parameter.type.name == "double" parameter.default_value.gsub(/\.$/,".0").gsub(/^\./,"0.") elsif parameter.type.ptr? &&(parameter.default_value == "0" || parameter.default_value = "NULL") # NULL pointer t = parameter.type.to_raw if t.extern_package_name "::#{t.extern_package_name}::#{normalize_type_name(t.full_name)}::null" else "#{normalize_type_name(t.full_name)}::null" end else normalize_type_name(parameter.default_value) end else if(parameter.default_value.gsub(/^new /,"") =~ /([ \w:<>]*) *\((.*)\)/) value = $2 t = parameter.owner.owner.type($1,false) ops = Array(parameter.owner.owner.operation($1,false)) if !t t,ops = if t || !ops.empty? [t,ops] else ns = RBase.namespace($1) name = RBase.basename($1) if ns && name t = parameter.owner.owner.type(ns,false) ops = Array(t.operation(name,false)) if t [t,ops] else [nil,nil] end end s = if ops && !ops.empty? if t if t.extern_package_name "::#{t.extern_package_name}::#{normalize_type_name(t.full_name)}::#{normalize_method_name(ops.first.name)}(#{(value)})" else "#{normalize_type_name(t.full_name)}::#{normalize_method_name(ops.first.name)}(#{(value)})" end else "#{normalize_method_name(ops.first.name)}(#{(value)})" end elsif t t = t.to_raw if t.extern_package_name "::#{t.extern_package_name}::#{normalize_type_name(t.full_name)}.new(#{(value)})" else "#{normalize_type_name(t.full_name)}.new(#{(value)})" end end else parameter.default_value end end if val val else raise "cannot parse default parameter value #{parameter.default_value} for #{parameter.owner.signature}" end end |
.normalize_doc(str) ⇒ Object
24 25 26 27 28 29 30 31 32 |
# File 'lib/rbind/generator_ruby.rb', line 24 def self.normalize_doc(str) return nil if !str || str.empty? s = str str = str.gsub(/\$\$(.*)\$\$/m) do "})" end str = str.gsub(/^ *#?/,"# ") "#{str.chomp}\n" end |
.normalize_enum_name(name) ⇒ Object
238 239 240 241 242 243 244 |
# File 'lib/rbind/generator_ruby.rb', line 238 def self.normalize_enum_name(name) name = GeneratorRuby.normalize_basic_type_name_ffi name #to lower and substitute namespace :: with _ name = name.gsub("::","_") name = name.downcase name end |
.normalize_method_name(orig_name) ⇒ Object
normalize c method to meet ruby conventions see unit tests
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/rbind/generator_ruby.rb', line 218 def self.normalize_method_name(orig_name) #remove cprefix and replaced _X with #X name = orig_name.to_s.gsub(/\A#{RBase.cprefix}/, "") .gsub(/_((?<!\A)\p{Lu})/u, '#\1') #replaced X with _x name = name.gsub(/(?<!\A)[\p{Lu}\d]/u, '_\0').downcase #replaced _x_ with #x# name = name.to_s.gsub(/[_#]([a-zA-Z\d])[_#]/u, '#\1#') #replaced _x$ with #x name = name.to_s.gsub(/[_#]([a-zA-Z\d])$/u, '#\1') #replaced ## with _ name = name.gsub(/##/, '_') #replace #xx with _xx name = name.gsub(/#([a-zA-Z\d]{2})/, '_\1') #remove all remaining # name = name.gsub(/#/, '') name = normalize_alias_method_name(name) raise RuntimeError, "Normalization failed: generated empty name for #{orig_name}" if name.empty? name end |
.normalize_type_name(name) ⇒ Object
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/rbind/generator_ruby.rb', line 127 def self.normalize_type_name(name) name.gsub!(" ","") # map template classes # std::vector<std::string> -> Std::Vector::Std_String if name =~ /([\w:]*)<(.*)>$/ return "#{normalize_type_name($1)}::#{normalize_type_name($2).gsub("::","_")}" else name end # custom normalization if @on_normalize_type_name n = @on_normalize_type_name.call(name) return n if n end # Parse constant declaration with suffix like 1000000LL if name =~ /^([0-9]+)[uUlL]{0,2}/ name = $1 return name end # map all uint ... to Fixnum if name =~ /^u?int\d*$/ || name =~ /^u?int\d+_t$/ return "Fixnum" end name = name.gsub(/^_/,"") names = name.split("::").map do |n| n.gsub(/^(\w)(.*)/) do $1.upcase+$2 end end n = names.last.split("_").first if n == n.upcase return names.join("::") end name = names.join("::").split("_").map do |n| n.gsub(/^(\w)(.*)/) do $1.upcase+$2 end end.join("") end |
Instance Method Details
#generate(path = @output_path) ⇒ Object
802 803 804 805 806 807 808 809 810 811 812 |
# File 'lib/rbind/generator_ruby.rb', line 802 def generate(path=@output_path) @output_path = path FileUtils.mkdir_p(path) if path && !File.directory?(path) file_rbind = File.new(File.join(path,"#{file_prefix}.rb"),"w") file_types = File.new(File.join(path,"#{file_prefix}_types.rb"),"w") types = RTypeHelper.new(@module_name,@root,compact_namespace) file_types.write types.result rbind = RBindHelper.new(@module_name,self,compact_namespace) file_rbind.write @rbind_wrapper.result(rbind.binding) end |