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_const_value(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, template = false) ⇒ 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.
Methods included from Hooks
Constructor Details
#initialize(root, module_name = "Rbind", library_name = "rbind_lib") ⇒ GeneratorRuby
Returns a new instance of GeneratorRuby.
836 837 838 839 840 841 842 |
# File 'lib/rbind/generator_ruby.rb', line 836 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.
829 830 831 |
# File 'lib/rbind/generator_ruby.rb', line 829 def compact_namespace @compact_namespace end |
#file_prefix ⇒ Object
Returns the value of attribute file_prefix.
828 829 830 |
# File 'lib/rbind/generator_ruby.rb', line 828 def file_prefix @file_prefix end |
#library_name ⇒ Object
Returns the value of attribute library_name.
826 827 828 |
# File 'lib/rbind/generator_ruby.rb', line 826 def library_name @library_name end |
#module_name ⇒ Object
Returns the value of attribute module_name.
824 825 826 |
# File 'lib/rbind/generator_ruby.rb', line 824 def module_name @module_name end |
#output_path ⇒ Object
Returns the value of attribute output_path.
827 828 829 |
# File 'lib/rbind/generator_ruby.rb', line 827 def output_path @output_path end |
#required_module_names ⇒ Object
Returns the value of attribute required_module_names.
825 826 827 |
# File 'lib/rbind/generator_ruby.rb', line 825 def required_module_names @required_module_names end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
830 831 832 |
# File 'lib/rbind/generator_ruby.rb', line 830 def root @root end |
Class Method Details
.keyword?(name) ⇒ Boolean
21 22 23 |
# File 'lib/rbind/generator_ruby.rb', line 21 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
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/rbind/generator_ruby.rb', line 193 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
39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/rbind/generator_ruby.rb', line 39 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
183 184 185 186 187 188 189 190 191 |
# File 'lib/rbind/generator_ruby.rb', line 183 def self.normalize_basic_type_name_ffi(name) n = ffi_type_map[name] n ||= name if n =~ /\*/ "pointer" else n end end |
.normalize_const_value(name) ⇒ Object
256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
# File 'lib/rbind/generator_ruby.rb', line 256 def self.normalize_const_value(name) name = name.to_s.gsub(" ","") # Parse constant declaration with suffix like 1000000LL if name =~ /^([0-9]+)[uUlL]{0,2}/ name = $1 return name end # upcase first letter name = name.gsub(/\w*/) do |n| next unless n.size > 0 n[0].upcase+n[1,n.size-1] end name end |
.normalize_default_value(parameter) ⇒ Object
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 125 126 127 |
# File 'lib/rbind/generator_ruby.rb', line 54 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.is_a? REnum ":#{parameter.default_value.split("::").last}" elsif parameter.type.name == "float" parameter.default_value.gsub("f","").gsub("F","").gsub(/\.$/,".0").gsub(/^\./,"0.") 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
25 26 27 28 29 30 31 32 33 |
# File 'lib/rbind/generator_ruby.rb', line 25 def self.normalize_doc(str) return nil if !str || str.empty? s = str str = str.gsub(/\$\$(.*)\$\$/m) do "![equation](http://latex.codecogs.com/gif.latex?#{URI::encode($1.to_s)})" end str = str.gsub(/^ *#?/,"# ") "#{str.chomp}\n" end |
.normalize_enum_name(name) ⇒ Object
248 249 250 251 252 253 254 |
# File 'lib/rbind/generator_ruby.rb', line 248 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
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/rbind/generator_ruby.rb', line 228 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, template = false) ⇒ Object
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 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/rbind/generator_ruby.rb', line 130 def self.normalize_type_name(name,template=false) name.gsub!(" ","") # map template classes # std::vector<std::string> -> Std::Vector::Std_String if name =~ /([\w:]*)<(.*)>$/ name = $1 names = $2.split(",") names.map! do |val| normalize_type_name(val,true).gsub("::","_") end return "#{normalize_type_name(name,true)}::#{names.join("_")}" 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 !template if name =~ /^u?int\d*$/ || name =~ /^u?int\d+_t$/ return "Fixnum" end 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
844 845 846 847 848 849 850 851 852 853 854 |
# File 'lib/rbind/generator_ruby.rb', line 844 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 |