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, 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.
Constructor Details
#initialize(root, module_name = "Rbind", library_name = "rbind_lib") ⇒ GeneratorRuby
Returns a new instance of GeneratorRuby.
802 803 804 805 806 807 808 |
# File 'lib/rbind/generator_ruby.rb', line 802 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.
795 796 797 |
# File 'lib/rbind/generator_ruby.rb', line 795 def compact_namespace @compact_namespace end |
#file_prefix ⇒ Object
Returns the value of attribute file_prefix.
794 795 796 |
# File 'lib/rbind/generator_ruby.rb', line 794 def file_prefix @file_prefix end |
#library_name ⇒ Object
Returns the value of attribute library_name.
792 793 794 |
# File 'lib/rbind/generator_ruby.rb', line 792 def library_name @library_name end |
#module_name ⇒ Object
Returns the value of attribute module_name.
790 791 792 |
# File 'lib/rbind/generator_ruby.rb', line 790 def module_name @module_name end |
#output_path ⇒ Object
Returns the value of attribute output_path.
793 794 795 |
# File 'lib/rbind/generator_ruby.rb', line 793 def output_path @output_path end |
#required_module_names ⇒ Object
Returns the value of attribute required_module_names.
791 792 793 |
# File 'lib/rbind/generator_ruby.rb', line 791 def required_module_names @required_module_names end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
796 797 798 |
# File 'lib/rbind/generator_ruby.rb', line 796 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
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 215 216 217 |
# File 'lib/rbind/generator_ruby.rb', line 186 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
176 177 178 179 180 181 182 183 184 |
# File 'lib/rbind/generator_ruby.rb', line 176 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
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 |
# 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.name == "float" parameter.default_value.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 "})" end str = str.gsub(/^ *#?/,"# ") "#{str.chomp}\n" end |
.normalize_enum_name(name) ⇒ Object
241 242 243 244 245 246 247 |
# File 'lib/rbind/generator_ruby.rb', line 241 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
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/rbind/generator_ruby.rb', line 221 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
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 172 173 174 |
# File 'lib/rbind/generator_ruby.rb', line 128 def self.normalize_type_name(name,template=false) name.gsub!(" ","") # map template classes # std::vector<std::string> -> Std::Vector::Std_String if name =~ /([\w:]*)<(.*)>$/ return "#{normalize_type_name($1,true)}::#{normalize_type_name($2,true).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 !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
810 811 812 813 814 815 816 817 818 819 820 |
# File 'lib/rbind/generator_ruby.rb', line 810 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 |