rubex 0.0.1 → 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/.travis.yml +14 -0
  4. data/CONTRIBUTING.md +101 -0
  5. data/HISTORY.md +3 -0
  6. data/README.md +112 -297
  7. data/REFERENCE.md +753 -0
  8. data/Rakefile +4 -1
  9. data/TUTORIAL.md +234 -0
  10. data/bin/rubex +1 -1
  11. data/docs/_config.yml +1 -0
  12. data/docs/index.html +1 -0
  13. data/examples/c_struct_interface/c_struct_interface.rb +6 -0
  14. data/examples/c_struct_interface/c_struct_interface.rubex +47 -0
  15. data/examples/linked_list/linked_list.rubex +39 -0
  16. data/examples/linked_list/rb_linked_list.rb +8 -0
  17. data/examples/rcsv wrapper/rcsv/README.md +1 -0
  18. data/examples/rcsv wrapper/rcsv/Rakefile +7 -0
  19. data/examples/rcsv wrapper/rcsv/ext/rcsv/extconf.rb +3 -0
  20. data/examples/rcsv wrapper/rcsv/ext/rcsv/rcsv.c +302 -0
  21. data/examples/rcsv wrapper/rcsv/ext/rcsv/rcsv.rubex +124 -0
  22. data/examples/rcsv wrapper/rcsv/lib/rcsv.rb +8 -0
  23. data/examples/rcsv wrapper/rcsv/lib/rcsv.so +0 -0
  24. data/examples/rcsv wrapper/rcsv/lib/rcsv/version.rb +1 -0
  25. data/examples/rcsv wrapper/rcsv/rcsv.gemspec +27 -0
  26. data/examples/rcsv wrapper/rcsv/spec/rcsv.csv +5 -0
  27. data/examples/rcsv wrapper/rcsv/spec/rcsv_spec.rb +17 -0
  28. data/examples/rcsv wrapper/rcsv/spec/spec_helper.rb +6 -0
  29. data/{spec/fixtures/basic_ruby_method/Makefile → examples/rcsv wrapper/rcsv/tmp/x86_64-linux/rcsv/2.3.3/Makefile } +20 -20
  30. data/examples/rcsv wrapper/rcsv/tmp/x86_64-linux/rcsv/2.3.3/rcsv.o +0 -0
  31. data/examples/rcsv wrapper/rcsv/tmp/x86_64-linux/rcsv/2.3.3/rcsv.so +0 -0
  32. data/examples/rcsv wrapper/rcsv/tmp/x86_64-linux/stage/lib/rcsv.so +0 -0
  33. data/lib/rubex.rb +6 -50
  34. data/lib/rubex/ast.rb +1 -3
  35. data/lib/rubex/ast/expression.rb +1257 -8
  36. data/lib/rubex/ast/node.rb +226 -28
  37. data/lib/rubex/ast/statement.rb +1162 -35
  38. data/lib/rubex/ast/top_statement.rb +815 -0
  39. data/lib/rubex/code_writer.rb +103 -26
  40. data/lib/rubex/compiler.rb +72 -0
  41. data/lib/rubex/compiler_config.rb +19 -0
  42. data/lib/rubex/constants.rb +145 -8
  43. data/lib/rubex/data_type.rb +667 -4
  44. data/lib/rubex/error.rb +15 -0
  45. data/lib/rubex/helpers.rb +154 -0
  46. data/lib/rubex/lexer.rex +186 -22
  47. data/lib/rubex/lexer.rex.rb +261 -35
  48. data/lib/rubex/parser.racc +876 -28
  49. data/lib/rubex/parser.racc.rb +2845 -90
  50. data/lib/rubex/rake_task.rb +34 -0
  51. data/lib/rubex/symbol_table/entry.rb +17 -3
  52. data/lib/rubex/symbol_table/scope.rb +298 -25
  53. data/lib/rubex/version.rb +1 -1
  54. data/rubex.gemspec +11 -3
  55. data/spec/basic_ruby_method_spec.rb +15 -21
  56. data/spec/binding_ptr_args_spec.rb +33 -0
  57. data/spec/bitwise_operators_spec.rb +40 -0
  58. data/spec/blocks_spec.rb +35 -0
  59. data/spec/c_bindings_spec.rb +36 -0
  60. data/spec/c_constants_spec.rb +33 -0
  61. data/spec/c_function_ptrs_spec.rb +38 -0
  62. data/spec/c_functions_spec.rb +35 -0
  63. data/spec/c_struct_interface_spec.rb +38 -0
  64. data/spec/call_by_reference_spec.rb +33 -0
  65. data/spec/class_methods_spec.rb +33 -0
  66. data/spec/class_spec.rb +40 -0
  67. data/spec/comments_spec.rb +33 -0
  68. data/spec/default_args_spec.rb +37 -0
  69. data/spec/error_handling_spec.rb +42 -0
  70. data/spec/examples_spec.rb +52 -0
  71. data/spec/expressions_spec.rb +33 -0
  72. data/spec/fixtures/basic_ruby_method/basic_ruby_method.rubex +2 -0
  73. data/spec/fixtures/binding_ptr_args/binding_ptr_args.rubex +30 -0
  74. data/spec/fixtures/bitwise_operators/bitwise_operators.rubex +40 -0
  75. data/spec/fixtures/blocks/blocks.rubex +11 -0
  76. data/spec/fixtures/c_bindings/c_bindings.rubex +58 -0
  77. data/spec/fixtures/c_constants/c_constants.rubex +7 -0
  78. data/spec/fixtures/c_function_ptrs/c_function_ptrs.rubex +52 -0
  79. data/spec/fixtures/c_functions/c_functions.rubex +25 -0
  80. data/spec/fixtures/c_struct_interface/c_struct_interface.rubex +34 -0
  81. data/spec/fixtures/call_by_reference/call_by_reference.rubex +30 -0
  82. data/spec/fixtures/class/class.rubex +20 -0
  83. data/spec/fixtures/class_methods/class_methods.rubex +12 -0
  84. data/spec/fixtures/comments/comments.rubex +9 -0
  85. data/spec/fixtures/default_args/default_args.rubex +11 -0
  86. data/spec/fixtures/error_handling/error_handling.rubex +54 -0
  87. data/spec/fixtures/examples/array_to_hash.rubex +14 -0
  88. data/spec/fixtures/examples/rcsv.csv +5 -0
  89. data/spec/fixtures/examples/rcsv.rubex +329 -0
  90. data/spec/fixtures/expressions/expressions.rubex +10 -0
  91. data/spec/fixtures/if_else/if_else.rubex +77 -0
  92. data/spec/fixtures/implicit_lib_include/implicit_lib_include.rubex +15 -0
  93. data/spec/fixtures/init_ruby_objects_with_literal_syntax/init_ruby_objects_with_literal_syntax.rubex +17 -0
  94. data/spec/fixtures/loops/loops.rubex +33 -0
  95. data/spec/fixtures/recursion/recursion.rubex +9 -0
  96. data/spec/fixtures/ruby_constant_method_calls/ruby_constant_method_calls.rubex +17 -0
  97. data/spec/fixtures/ruby_operators/ruby_operators.rubex +29 -0
  98. data/spec/fixtures/ruby_raise/ruby_raise.rubex +13 -0
  99. data/spec/fixtures/ruby_strings/ruby_strings.rubex +19 -0
  100. data/spec/fixtures/ruby_strings/string_blank_bm.rb +37 -0
  101. data/spec/fixtures/ruby_symbols/ruby_symbols.rubex +12 -0
  102. data/spec/fixtures/ruby_types/ruby_types.rubex +15 -0
  103. data/spec/fixtures/statement_expression/statement_expression.rubex +23 -0
  104. data/spec/fixtures/static_array/static_array.rubex +20 -0
  105. data/spec/fixtures/string_literals/string_literals.rubex +15 -0
  106. data/spec/fixtures/struct/struct.rubex +82 -0
  107. data/spec/fixtures/typecasting/typecasting.rubex +23 -0
  108. data/spec/fixtures/var_declarations/var_declarations.rubex +39 -0
  109. data/spec/if_else_spec.rb +39 -0
  110. data/spec/implicit_lib_include_spec.rb +33 -0
  111. data/spec/init_ruby_objects_with_literal_syntax_spec.rb +39 -0
  112. data/spec/loops_spec.rb +34 -0
  113. data/spec/recursion_spec.rb +35 -0
  114. data/spec/ruby_constant_method_calls_spec.rb +35 -0
  115. data/spec/ruby_operators_spec.rb +40 -0
  116. data/spec/ruby_raise_spec.rb +35 -0
  117. data/spec/ruby_strings_spec.rb +33 -0
  118. data/spec/ruby_symbols_spec.rb +37 -0
  119. data/spec/ruby_types_spec.rb +35 -0
  120. data/spec/spec_helper.rb +54 -1
  121. data/spec/statement_expression_spec.rb +34 -0
  122. data/spec/static_array_spec.rb +33 -0
  123. data/spec/string_literals_spec.rb +34 -0
  124. data/spec/struct_spec.rb +36 -0
  125. data/spec/typecasting_spec.rb +38 -0
  126. data/spec/var_declarions_spec.rb +35 -0
  127. metadata +255 -29
  128. data/lib/rubex/ast/argument_list.rb +0 -20
  129. data/lib/rubex/ast/c_base_type.rb +0 -11
  130. data/lib/rubex/ast/ruby_method_def.rb +0 -84
  131. data/spec/fixtures/basic_ruby_method/basic.rb +0 -3
  132. data/spec/fixtures/basic_ruby_method/basic_ruby_method.c +0 -16
  133. data/spec/fixtures/basic_ruby_method/basic_ruby_method.o +0 -0
  134. data/spec/fixtures/basic_ruby_method/basic_ruby_method.so +0 -0
  135. data/spec/fixtures/basic_ruby_method/extconf.rb +0 -3
@@ -4,64 +4,141 @@ module Rubex
4
4
 
5
5
  def initialize target_name
6
6
  @code = "/* C extension for #{target_name}.\n"\
7
- "This file in generated by Rubex. Do not change!\n"\
8
- "*/\n"
7
+ "This file in generated by Rubex::Compiler. Do not change!\n"\
8
+ "File generation time: #{Time.now}."\
9
+ "*/\n\n"
9
10
  @indent = 0
10
11
  end
11
12
 
12
- def write_func_declaration return_type, c_name, args=""
13
- write_func_prototype return_type, c_name, args
13
+ # type - Return type of the method.
14
+ # c_name - C Name.
15
+ # args - Array of Arrays containing data type and variable name.
16
+ def write_func_declaration type:, c_name:, args: [], static: true
17
+ write_func_prototype type, c_name, args, static: static
14
18
  @code << ";"
15
19
  new_line
16
20
  end
17
21
 
18
- def write_func_definition_header return_type, c_name, args=""
19
- write_func_prototype return_type, c_name, args
20
- @code << "\n"
21
- @code << "{\n"
22
+ def colon
23
+ @code << ";"
24
+ new_line
25
+ end
26
+
27
+ def c_macro macro
28
+ @code << "#define #{macro}"
29
+ new_line
30
+ end
31
+
32
+ def write_c_method_header type: , c_name: , args: [], static: true
33
+ write_func_prototype type, c_name, args, static: static
34
+ end
35
+
36
+ def write_ruby_method_header type: , c_name:
37
+ args = [["int", "argc"], ["VALUE*", "argv"],
38
+ ["VALUE", "#{Rubex::ARG_PREFIX + "self"}"]]
39
+ write_func_prototype type, c_name, args
40
+ end
41
+
42
+ def write_location location
43
+ new_line
44
+ self << "/* Rubex file location: #{location} */"
45
+ new_line
46
+ end
47
+
48
+ def declare_variable type:, c_name:
49
+ @code << " "*@indent + "#{type} #{c_name};"
50
+ new_line
51
+ end
52
+
53
+ def declare_func_ptr var:
54
+ type = var.type
55
+ func = type.base_type
56
+ @code << " "*@indent
57
+ @code << "#{func.type.to_s} (#{type.ptr_level}#{func.c_name}) "
58
+ @code << "(" + func.arg_list.map { |e| e.type.to_s }.join(',') + ")"
59
+ @code << ";"
60
+ nl
22
61
  end
23
62
 
24
- def declare_variable var
25
- @code << "#{var.type.to_s} #{var.c_name};\n"
63
+ def declare_carray type:, c_name:, dimension:, value: nil
64
+ stmt = "#{type} #{c_name}[#{dimension}]"
65
+ stmt << " = {" + value.join(',') + "}" if value
66
+ stmt << ";"
67
+ self << stmt
68
+ nl
26
69
  end
27
-
28
- def << s
29
- @code << s
70
+
71
+ def init_variable lhs: , rhs:
72
+ stat = " "*@indent + "#{lhs} = #{rhs};"
73
+ @code << stat
74
+ new_line
75
+ end
76
+
77
+ def << str
78
+ str.each_line do |s|
79
+ @code << " "*@indent
80
+ @code << s
81
+ end
30
82
  end
31
83
 
32
84
  def new_line
33
85
  @code << "\n"
34
86
  end
87
+ alias :nl :new_line
35
88
 
36
89
  def indent
37
- @indent += 1
90
+ @indent += 2
38
91
  end
39
92
 
40
93
  def dedent
41
94
  raise "Cannot dedent, already 0." if @indent == 0
42
- @indent -= 1
95
+ @indent -= 2
43
96
  end
44
97
 
45
- def define_instance_method_under scope, name, c_name
46
- @code << "rb_define_method(" + scope.c_name + " ,\"" + name + "\", " +
47
- c_name + ", -1);\n"
98
+ def write_instance_method klass: , method_name: , method_c_name:
99
+ @code << " "*@indent + "rb_define_method(" + klass + " ,\"" +
100
+ method_name + "\", " + method_c_name + ", -1);"
101
+ new_line
102
+ end
103
+
104
+ def write_singleton_method klass:, method_name:, method_c_name:
105
+ @code << " "*@indent + "rb_define_singleton_method(" + klass + " ,\"" +
106
+ method_name + "\", " + method_c_name + ", -1);"
107
+ new_line
48
108
  end
49
109
 
50
110
  def to_s
51
111
  @code
52
112
  end
53
113
 
114
+ def lbrace
115
+ @code << (" "*@indent + "{")
116
+ end
117
+
118
+ def rbrace
119
+ @code << (" "*@indent + "}")
120
+ end
121
+
122
+ def block str="", &block
123
+ new_line
124
+ lbrace
125
+ indent
126
+ new_line
127
+ block.call
128
+ dedent
129
+ rbrace
130
+ @code << str
131
+ new_line
132
+ new_line
133
+ end
134
+
54
135
  private
55
136
 
56
- def write_func_prototype return_type, c_name, args
57
- @code << "#{return_type} #{c_name} "
137
+ def write_func_prototype return_type, c_name, args, static: true
138
+ @code << "#{static ? "static " : ""}#{return_type} #{c_name} "
58
139
  @code << "("
59
- if args.empty?
60
- @code << "int argc, VALUE* argv, VALUE #{Rubex::ARG_PREFIX}self"
61
- else
62
- @code << args
63
- end
64
- @code << ")"
140
+ @code << args.map { |type_arg| type_arg.join(" ") }.join(",")
141
+ @code << ")"
65
142
  end
66
143
  end
67
144
  end
@@ -0,0 +1,72 @@
1
+ module Rubex
2
+ class Compiler
3
+ CONFIG = Rubex::CompilerConfig.new
4
+
5
+ class << self
6
+ def compile path, test: false, directory: nil
7
+ tree = ast path, test: test
8
+ target_name = extract_target_name path
9
+ code = generate_code tree, target_name
10
+ ext = extconf target_name, directory: directory
11
+ CONFIG.flush
12
+
13
+ return [tree, code, ext] if test
14
+ write_files target_name, code, ext, directory: directory
15
+ end
16
+
17
+ def ast path, test: false
18
+ if test
19
+ parser = Rubex::Parser.new
20
+ parser.parse(path)
21
+ parser.do_parse
22
+ else
23
+ begin
24
+ parser = Rubex::Parser.new
25
+ parser.parse(path)
26
+ parser.do_parse
27
+ rescue Racc::ParseError => e
28
+ error_msg = "\nPARSE ERROR:\n"
29
+ error_msg << "Line: #{parser.string.split("\n")[parser.lineno-1]}\n"
30
+ error_msg << "Location: #{parser.location}\n"
31
+ error_msg << "Error:\n#{e}"
32
+ STDERR.puts error_msg
33
+ end
34
+ end
35
+ end
36
+
37
+ def extconf target_name, directory: nil
38
+ path = directory ? directory : "#{Dir.pwd}/#{target_name}"
39
+ extconf = ""
40
+ extconf << "require 'mkmf'\n"
41
+ extconf << "$libs += \" #{CONFIG.link_flags}\"\n"
42
+ extconf << "create_makefile('#{path}/#{target_name}')\n"
43
+ extconf
44
+ end
45
+
46
+ def generate_code tree, target_name
47
+ code = Rubex::CodeWriter.new target_name
48
+ raise "Must be a Rubex::AST::Node, not #{tree.class}" unless
49
+ tree.is_a? Rubex::AST::Node
50
+ tree.process_statements target_name, code
51
+ code
52
+ end
53
+
54
+ def extract_target_name path
55
+ File.basename(path).split('.')[0]
56
+ end
57
+
58
+ def write_files target_name, code, ext, directory: nil
59
+ path = directory ? directory : "#{Dir.pwd}/#{target_name}"
60
+ Dir.mkdir(path) unless directory
61
+
62
+ code_file = File.new "#{path}/#{target_name}.c", "w+"
63
+ code_file.puts code.to_s
64
+ code_file.close
65
+
66
+ extconf_file = File.new "#{path}/extconf.rb", "w+"
67
+ extconf_file.puts ext
68
+ extconf_file.close
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,19 @@
1
+ module Rubex
2
+ class CompilerConfig
3
+ def initialize
4
+ @links = []
5
+ end
6
+
7
+ def add_link link_str
8
+ @links << link_str
9
+ end
10
+
11
+ def link_flags
12
+ @links.map { |l| l.dup.prepend('-l') }.join(' ')
13
+ end
14
+
15
+ def flush
16
+ @links = []
17
+ end
18
+ end
19
+ end
@@ -1,17 +1,154 @@
1
1
  module Rubex
2
2
  RUBEX_PREFIX = "__rubex_"
3
-
4
- FUNC_PREFIX = RUBEX_PREFIX + "f_"
3
+ GLOBAL_PREFIX = "global_"
4
+
5
+ TEMP_PREFIX = RUBEX_PREFIX + "temp_"
6
+ RUBY_FUNC_PREFIX = RUBEX_PREFIX + "rb_f_"
7
+ C_FUNC_PREFIX = RUBEX_PREFIX + "c_f_"
5
8
  VAR_PREFIX = RUBEX_PREFIX + "v_"
6
- CLASS_PREFIX = RUBEX_PREFIX + "c_"
9
+ RUBY_CLASS_PREFIX = RUBEX_PREFIX + "rb_cls_"
10
+ ATTACH_CLASS_PREFIX = RUBEX_PREFIX + "attach_rb_cls"
7
11
  ARG_PREFIX = RUBEX_PREFIX + "arg_"
12
+ ARRAY_PREFIX = RUBEX_PREFIX + "arr_"
13
+ POINTER_PREFIX = RUBEX_PREFIX + "ptr_"
14
+ TYPE_PREFIX = RUBEX_PREFIX + "t_"
15
+
16
+ ACTUAL_ARGS_SUFFIX = "_actual_args"
8
17
 
9
18
  TYPE_MAPPINGS = {
10
- 'i32' => Rubex::DataType::CInt32,
11
- 'object' => Rubex::DataType::RubyObject
19
+ 'char' => Rubex::DataType::Char,
20
+ 'bool' => Rubex::DataType::CBoolean,
21
+ 'unsigned char' => Rubex::DataType::UChar,
22
+ 'i8' => Rubex::DataType::Int8,
23
+ 'i16' => Rubex::DataType::Int16,
24
+ 'i32' => Rubex::DataType::Int32,
25
+ 'i64' => Rubex::DataType::Int64,
26
+ 'u8' => Rubex::DataType::UInt8,
27
+ 'u16' => Rubex::DataType::UInt16,
28
+ 'u32' => Rubex::DataType::UInt32,
29
+ 'u64' => Rubex::DataType::UInt64,
30
+ 'int' => Rubex::DataType::Int,
31
+ 'unsigned int' => Rubex::DataType::UInt,
32
+ 'long int' => Rubex::DataType::LInt,
33
+ 'long' => Rubex::DataType::LInt,
34
+ 'unsigned long int' => Rubex::DataType::ULInt,
35
+ 'long long int' => Rubex::DataType::LLInt,
36
+ 'long long' => Rubex::DataType::LLInt,
37
+ 'unsigned long long int' => Rubex::DataType::ULLInt,
38
+ 'f32' => Rubex::DataType::F32,
39
+ 'float' => Rubex::DataType::F32,
40
+ 'f64' => Rubex::DataType::F64,
41
+ 'double' => Rubex::DataType::F64,
42
+ 'object' => Rubex::DataType::RubyObject,
43
+ 'void' => Rubex::DataType::Void,
44
+ 'size_t' => Rubex::DataType::Size_t,
45
+ 'str' => Rubex::DataType::RubyString,
46
+ 'arr' => Rubex::DataType::RubyArray,
47
+ 'hsh' => Rubex::DataType::RubyHash
48
+ }
49
+
50
+ CUSTOM_TYPES = {}
51
+
52
+ DEFAULT_CLASS_MAPPINGS = {
53
+ "Kernel" => "rb_mKernel",
54
+ "Comparable" => "rb_mComparable",
55
+ "Enumerable" => "rb_mEnumerable",
56
+ "Errno" => "rb_mErrno",
57
+ "FileTest" => "rb_mFileTest",
58
+ "GC" => "rb_mGC",
59
+ "Math" => "rb_mMath",
60
+ "Process" => "rb_mProcess",
61
+ "WaitReadable" => "rb_mWaitReadable",
62
+ "WaitWritable" => "rb_mWaitWritable",
63
+ "BasicObject" => "rb_cBasicObject",
64
+ "Object" => "rb_cObject",
65
+ "Array" => "rb_cArray",
66
+ "Bignum" => "rb_cBignum",
67
+ "Binding" => "rb_cBinding",
68
+ "Class" => "rb_cClass",
69
+ "Cont" => "rb_cCont",
70
+ "Dir" => "rb_cDir",
71
+ "Data" => "rb_cData",
72
+ "FalseClass" => "rb_cFalseClass",
73
+ "Encoding" => "rb_cEncoding",
74
+ "Enumerator" => "rb_cEnumerator",
75
+ "File" => "rb_cFile",
76
+ "Fixnum" => "rb_cFixnum",
77
+ "Float" => "rb_cFloat",
78
+ "Hash" => "rb_cHash",
79
+ "Integer" => "rb_cInteger",
80
+ "IO" => "rb_cIO",
81
+ "Match" => "rb_cMatch",
82
+ "Method" => "rb_cMethod",
83
+ "Module" => "rb_cModule",
84
+ "NameErrorMesg" => "rb_cNameErrorMesg",
85
+ "NilClass" => "rb_cNilClass",
86
+ "Numeric" => "rb_cNumeric",
87
+ "Proc" => "rb_cProc",
88
+ "Random" => "rb_cRandom",
89
+ "Range" => "rb_cRange",
90
+ "Rational" => "rb_cRational",
91
+ "Complex" => "rb_cComplex",
92
+ "Regexp" => "rb_cRegexp",
93
+ "Stat" => "rb_cStat",
94
+ "String" => "rb_cString",
95
+ "Struct" => "rb_cStruct",
96
+ "Symbol" => "rb_cSymbol",
97
+ "Thread" => "rb_cThread",
98
+ "Time" => "rb_cTime",
99
+ "TrueClass" => "rb_cTrueClass",
100
+ "UnboundMethod" => "rb_cUnboundMethod",
101
+ "Exception" => "rb_eException",
102
+ "StandardError" => "rb_eStandardError",
103
+ "SystemExit" => "rb_eSystemExit",
104
+ "Interrupt" => "rb_eInterrupt",
105
+ "Signal" => "rb_eSignal",
106
+ "Fatal" => "rb_eFatal",
107
+ "ArgumentError" => "rb_eArgError",
108
+ "EOFError" => "rb_eEOFError",
109
+ "IndexError" => "rb_eIndexError",
110
+ "StopIteration" => "rb_eStopIteration",
111
+ "KeyError" => "rb_eKeyError",
112
+ "RangeError" => "rb_eRangeError",
113
+ "IOError" => "rb_eIOError",
114
+ "RuntimeError" => "rb_eRuntimeError",
115
+ "SecurityError" => "rb_eSecurityError",
116
+ "SystemCallError" => "rb_eSystemCallError",
117
+ "ThreadError" => "rb_eThreadError",
118
+ "TypeError" => "rb_eTypeError",
119
+ "ZeroDivError" => "rb_eZeroDivError",
120
+ "NotImpError" => "rb_eNotImpError",
121
+ "NoMemError" => "rb_eNoMemError",
122
+ "NoMethodError" => "rb_eNoMethodError",
123
+ "FloatDomainError" => "rb_eFloatDomainError",
124
+ "LocalJumpError" => "rb_eLocalJumpError",
125
+ "SysStackError" => "rb_eSysStackError",
126
+ "RegexpError" => "rb_eRegexpError",
127
+ "EncodingError" => "rb_eEncodingError",
128
+ "EncCompatError" => "rb_eEncCompatError",
129
+ "ScriptError" => "rb_eScriptError",
130
+ "NameError" => "rb_eNameError",
131
+ "SyntaxError" => "rb_eSyntaxError",
132
+ "LoadError" => "rb_eLoadError",
133
+ "MathDomainError" => "rb_eMathDomainError",
134
+ "STDIN" => "rb_stdin",
135
+ "STDOUT" => "rb_stdout",
136
+ "STDERR" => "rb_stderr",
12
137
  }
13
138
 
14
- CLASS_MAPPINGS = {
15
- 'Object' => 'rb_cObject'
139
+ C_MACRO_INT2BOOL = Rubex::RUBEX_PREFIX + "INT2BOOL"
140
+ C_FUNC_CHAR2RUBYSTR = Rubex::RUBEX_PREFIX + "char2rubystr"
141
+
142
+ ALLOC_FUNC_NAME = 'allocate'
143
+ DEALLOC_FUNC_NAME = 'deallocate'
144
+ MEMCOUNT_FUNC_NAME = 'memcount'
145
+ GET_STRUCT_FUNC_NAME = 'get_struct'
146
+
147
+ # Maps regexes to the type of the variable for conversion from literal
148
+ # to the correct type of Ruby object.
149
+ LITERAL_MAPPINGS = {
150
+ /'.\'/ => Rubex::DataType::Char,
151
+ /-?\d+/ => Rubex::DataType::Int,
152
+ /-?\d+\.\d+/ => Rubex::DataType::F64
16
153
  }
17
- end
154
+ end
@@ -1,15 +1,678 @@
1
1
  module Rubex
2
2
  module DataType
3
+ # Citations
4
+ # Printf arguments:
5
+ # http://www.thinkage.ca/english/gcos/expl/c/lib/printf.html
6
+ module Helpers
7
+ include ::Comparable
8
+ [
9
+ :float?, :float32?, :float64?,
10
+ :int?, :int8?, :int16?, :int32?, :int64?,
11
+ :uint?, :uint8?, :uint16?, :uint32?, :uint64?,
12
+ :lint?, :ulint?, :llint?, :ullint?,
13
+ :char?, :object?, :bool?, :carray?, :cbool?,
14
+ :cptr?, :nil_type?, :struct_or_union?,
15
+ :alias_type?, :string?, :cstr?, :ruby_class?,
16
+ :ruby_method?, :c_function?, :ruby_constant?, :void?,
17
+ :ruby_string?, :uchar?, :ruby_array?, :ruby_hash?
18
+ ].each do |dtype|
19
+ define_method(dtype) { return false }
20
+ end
21
+
22
+ def == other
23
+ self.class == other.class
24
+ end
25
+
26
+ def to_ruby_object(arg); arg; end
27
+
28
+ def from_ruby_object(arg); arg; end
29
+
30
+ def base_type; self; end
31
+
32
+ # Helper function to know if a dtype is a char pointer.
33
+ def char_ptr?
34
+ if self.cptr? && self.base_type.char?
35
+ true
36
+ else
37
+ false
38
+ end
39
+ end
40
+
41
+ def c_function_ptr?
42
+ if self.cptr? && self.base_type.c_function?
43
+ true
44
+ else
45
+ false
46
+ end
47
+ end
48
+ end
49
+
50
+ module IntHelpers
51
+ include Helpers
52
+ def to_ruby_object(arg); "INT2NUM(#{arg})"; end
53
+ end
54
+
55
+ module UIntHelpers
56
+ include Helpers
57
+ def to_ruby_object(arg); "UINT2NUM(#{arg})"; end
58
+ end
59
+
60
+ module FloatHelpers
61
+ include Helpers
62
+ end
63
+
64
+ class Void
65
+ include Helpers
66
+
67
+ def void?; true; end
68
+
69
+ def to_s; "void"; end
70
+ end
71
+
3
72
  class RubyObject
73
+ include Helpers
4
74
  def to_s; "VALUE"; end
75
+
76
+ def object?; true; end
77
+
78
+ def p_formatter; "%s"; end
79
+ end
80
+
81
+ class RubySymbol < RubyObject
82
+ def ruby_symbol?; true; end
83
+ end
84
+
85
+ class RubyString < RubyObject
86
+ def ruby_string?; true; end
87
+ end
88
+
89
+ class RubyArray < RubyObject
90
+ def ruby_array?; true; end
91
+ end
92
+
93
+ class RubyHash < RubyObject
94
+ def ruby_hash?; true; end
95
+ end
96
+
97
+ class Char
98
+ include Helpers
99
+ def to_s; "char"; end
100
+
101
+ def to_ruby_object(arg, literal=false)
102
+ "#{Rubex::C_FUNC_CHAR2RUBYSTR}(#{arg})"
103
+ end
104
+
105
+ def from_ruby_object(arg); "(char)NUM2INT(#{arg})"; end
106
+
107
+ def p_formatter; "%c"; end
108
+
109
+ def char?; true; end
110
+
111
+ def <=> other
112
+ if other.char?
113
+ return 0
114
+ else
115
+ return 1
116
+ end
117
+ end
118
+ end
119
+
120
+ class UChar
121
+ include Helpers
122
+
123
+ def to_s; "unsigned char"; end
124
+
125
+ def from_ruby_object(arg); "(unsigned char)NUM2INT(#{arg})"; end
126
+
127
+ def p_formatter; "%d"; end
128
+
129
+ def uchar?; true; end
130
+
131
+ def <=> other
132
+ if other.char? || other.uchar?
133
+ return 0
134
+ else
135
+ return 1
136
+ end
137
+ end
138
+ end
139
+
140
+ class Int8
141
+ include IntHelpers
142
+
143
+ def to_s; "int8_t"; end
144
+
145
+ def from_ruby_object(arg); "(int8_t)NUM2INT(#{arg})"; end
146
+
147
+ def int8?; true; end
148
+
149
+ def p_formatter; "%d"; end
150
+
151
+ def <=> other
152
+ if other.char?
153
+ return 1
154
+ elsif other.int8?
155
+ return 0
156
+ else
157
+ return -1
158
+ end
159
+ end
160
+ end
161
+
162
+ class Int16
163
+ include IntHelpers
164
+ def to_s; "int16_t"; end
165
+
166
+ def from_ruby_object(arg); "(int16_t)NUM2INT(#{arg})"; end
167
+
168
+ def int16?; true; end
169
+
170
+ def p_formatter; "%d"; end
171
+
172
+ def <=> other
173
+ if other.char? || other.int8?
174
+ return 1
175
+ elsif other.int16?
176
+ return 0
177
+ else
178
+ return -1
179
+ end
180
+ end
5
181
  end
6
182
 
7
- class CInt32
183
+ class Int32
184
+ include IntHelpers
8
185
  def to_s; "int32_t"; end
9
186
 
10
- def to_ruby_function; "INT2NUM"; end
187
+ def from_ruby_object(arg); "(int32_t)NUM2INT(#{arg})"; end
188
+
189
+ def int32?; true; end
190
+
191
+ def p_formatter; "%d"; end
192
+
193
+ def <=> other
194
+ if other.char? || other.int8? || other.int16?
195
+ return 1
196
+ elsif other.int32? || other.int?
197
+ return 0
198
+ else
199
+ return -1
200
+ end
201
+ end
202
+ end
203
+
204
+ class Int64
205
+ include IntHelpers
206
+ def to_s; "int64_t"; end
207
+
208
+ def to_ruby_object(arg); "LONG2NUM(#{arg})"; end
209
+
210
+ def from_ruby_object(arg); "(int64_t)NUM2LONG(#{arg})"; end
211
+
212
+ def p_formatter; "%ld"; end
213
+
214
+ def int64?; true; end
215
+
216
+ def <=> other
217
+ if other.char? || other.int8? || other.int16? || other.int32? ||
218
+ other.int?
219
+ return 1
220
+ elsif other.int64?
221
+ return 0
222
+ else
223
+ return -1
224
+ end
225
+ end
226
+ end
227
+
228
+ class UInt8
229
+ include UIntHelpers
230
+ def to_s; "uint8_t"; end
231
+
232
+ def from_ruby_object(arg); "(uint8_t)NUM2UINT(#{arg})"; end
233
+
234
+ def uint8?; true; end
235
+
236
+ def p_formatter; "%u"; end
237
+ end
238
+
239
+ class UInt16
240
+ include UIntHelpers
241
+ def to_s; "uint16_t"; end
242
+
243
+ def from_ruby_object(arg); "(uint16_t)NUM2UINT(#{arg})"; end
244
+
245
+ def uint16?; true; end
246
+
247
+ def p_formatter; "%u"; end
248
+ end
249
+
250
+ class UInt32
251
+ include UIntHelpers
252
+ def to_s; "uint32_t"; end
253
+
254
+ def from_ruby_object(arg); "(int32_t)NUM2UINT(#{arg})"; end
255
+
256
+ def uint32?; true; end
257
+
258
+ def p_formatter; "%u"; end
259
+ end
260
+
261
+ class UInt64
262
+ include UIntHelpers
263
+ def to_s; "uint64_t"; end
264
+
265
+ def to_ruby_object(arg); "ULONG2NUM(#{arg})"; end
266
+
267
+ def from_ruby_object(arg); "(int64_t)NUM2UINT(#{arg})"; end
268
+
269
+ def uint64?; true; end
270
+
271
+ def p_formatter; "%lu"; end
272
+ end
273
+
274
+ class Int
275
+ include IntHelpers
276
+ def to_s; "int"; end
277
+
278
+ def from_ruby_object(arg); "NUM2INT(#{arg})"; end
279
+
280
+ def int?; true; end
281
+
282
+ def p_formatter; "%d"; end
283
+
284
+ def <=> other
285
+ if other.char? || other.int8? || other.int16?
286
+ return 1
287
+ elsif other.int? || other.int32?
288
+ return 0
289
+ else # other is int64 or greater
290
+ return -1
291
+ end
292
+ end
293
+ end
294
+
295
+ class CBoolean < Int
296
+ def cbool?; true; end
297
+
298
+ def to_ruby_object arg
299
+ Rubex::C_MACRO_INT2BOOL + "(" + arg + ")"
300
+ end
301
+ end
302
+
303
+ class UInt
304
+ include UIntHelpers
305
+ def to_s; "unsigned int"; end
306
+
307
+ def from_ruby_object(arg); "(unsigned int)NUM2UINT(#{arg})"; end
308
+
309
+ def uint?; true; end
310
+
311
+ def p_formatter; "%u"; end
312
+
313
+ def <=> other
314
+ if other.char? || other.int8? || other.int16? || other.uint8? || other.uint16?
315
+ return 1
316
+ elsif other.uint? || other.int? || other.int32? || other.uint32?
317
+ return 0
318
+ else
319
+ return -1
320
+ end
321
+ end
322
+ end
323
+
324
+ class LInt
325
+ include IntHelpers
326
+ def to_s; "long int"; end
11
327
 
12
- def from_ruby_function; "NUM2INT"; end
328
+ def to_ruby_object(arg); "LONG2NUM(#{arg})"; end
329
+
330
+ def from_ruby_object(arg); "NUM2LONG(#{arg})"; end
331
+
332
+ def lint?; true; end
333
+
334
+ def p_formatter; "%ld"; end
335
+
336
+ def <=> other
337
+ if other.char? || other.int8? || other.int16? || other.int32? ||
338
+ other .int64? || other.uint8? || other.uint16? || other.uint32? ||
339
+ other.int?
340
+ return 1
341
+ elsif other.lint?
342
+ return 0
343
+ else
344
+ return -1
345
+ end
346
+ end
347
+ end
348
+
349
+ class ULInt
350
+ include UIntHelpers
351
+ def to_s; "unsigned long int"; end
352
+
353
+ def to_ruby_object(arg); "ULONG2NUM(#{arg})"; end
354
+
355
+ def from_ruby_object(arg); "NUM2ULONG(#{arg})"; end
356
+
357
+ def ulint?; true; end
358
+
359
+ def p_formatter; "%lu"; end
360
+
361
+ def <=> other
362
+ if other.char? || other.int8? || other.int16? || other.int32? ||
363
+ other .int64? || other.uint8? || other.uint16? || other.uint32? ||
364
+ other.int?
365
+ return 1
366
+ elsif other.ulint?
367
+ return 0
368
+ else
369
+ return -1
370
+ end
371
+ end
372
+ end
373
+
374
+ class Size_t < ULInt
375
+ def to_s
376
+ "size_t"
377
+ end
378
+ end
379
+
380
+ class LLInt
381
+ include IntHelpers
382
+ def to_s; "long long int"; end
383
+
384
+ def to_ruby_object(arg); "LL2NUM(#{arg})"; end
385
+
386
+ def from_ruby_object(arg); "NUM2LL(#{arg})"; end
387
+
388
+ def llint?; true; end
389
+
390
+ def p_formatter; "%ll"; end
391
+ end
392
+
393
+ class ULLInt
394
+ include UIntHelpers
395
+ def to_s; "unsigned long long int"; end
396
+
397
+ def to_ruby_object(arg); "ULL2NUM(#{arg})"; end
398
+
399
+ def from_ruby_object(arg); "NUM2ULL(#{arg})"; end
400
+
401
+ def ullint?; true; end
402
+
403
+ def p_formatter; "%llu"; end
404
+ end
405
+
406
+ class F32
407
+ include FloatHelpers
408
+ def to_s; "float"; end
409
+
410
+ def to_ruby_object(arg); "rb_float_new((double)(#{arg}))"; end
411
+
412
+ def from_ruby_object(arg); "(float)NUM2DBL(#{arg})"; end
413
+
414
+ def float32?; true; end
415
+
416
+ def p_formatter; "%f"; end
417
+
418
+ def <=> other
419
+ if other.char? || other.int8? || other.int16? || other.int32? ||
420
+ other.int64? || other.int? || other.uint8? || other.uint16?||
421
+ other.uint32? || other.uint64?
422
+ return 1
423
+ elsif other.float32?
424
+ return 0
425
+ else # other is float64
426
+ return -1
427
+ end
428
+ end
429
+
430
+ end
431
+
432
+ class F64
433
+ include FloatHelpers
434
+ def to_s; "double"; end
435
+
436
+ def to_ruby_object(arg); "rb_float_new(#{arg})"; end
437
+
438
+ def from_ruby_object(arg); "NUM2DBL(#{arg})"; end
439
+
440
+ def float64?; true; end
441
+
442
+ def p_formatter; "%f"; end
443
+
444
+ def <=> other
445
+ if other.char? || other.int8? || other.int16? || other.int32? ||
446
+ other.int64? || other.int? || other.uint8? || other.uint16?||
447
+ other.uint32? || other.uint64? || other.float32?
448
+ return 1
449
+ elsif other.float64?
450
+ return 0
451
+ else
452
+ return -1
453
+ end
454
+ end
455
+ end
456
+
457
+ class CArray
458
+ include Helpers
459
+ # Dimension of the array
460
+ attr_reader :dimension
461
+ # Type of elements stored in array
462
+ attr_reader :type # FIXME: Make this base_type to make it more explicit.
463
+
464
+ def initialize dimension, type
465
+ @dimension, @type = dimension, type
466
+ end
467
+
468
+ def carray?; true; end
469
+
470
+ def <=> other
471
+ if self.class == other.class
472
+ @type <=> other.type
473
+ else
474
+ @type <=> other
475
+ end
476
+ end
477
+
478
+ def base_type
479
+ @type
480
+ end
481
+ end
482
+
483
+ class CPtr
484
+ include Helpers
485
+ # The data type that this pointer is pointing to.
486
+ attr_reader :type
487
+
488
+ def initialize type
489
+ @type = type
490
+ end
491
+
492
+ def p_formatter
493
+ "%s" if char_ptr?
494
+ end
495
+
496
+ def cptr?; true; end
497
+
498
+ def to_s
499
+ base_type = @type.base_type
500
+ if base_type.c_function?
501
+ ptr = ptr_level
502
+
503
+ str = "#{base_type.type.to_s} (#{ptr} #{base_type.c_name.to_s})"
504
+ str << "(" + base_type.arg_list.map { |e| e.type.to_s }.join(',') + ")"
505
+ else
506
+ t = @type
507
+ str = "*"
508
+ if t.cptr?
509
+ str << "*"
510
+ t = t.type
511
+ end
512
+ str.prepend t.to_s
513
+ str
514
+ end
515
+ end
516
+
517
+ def base_type
518
+ return @type if !@type.is_a?(self.class)
519
+ return @type.base_type
520
+ end
521
+
522
+ def ptr_level
523
+ temp = @type
524
+ ptr = "*"
525
+ while temp.cptr?
526
+ ptr << "*"
527
+ temp = @type.type
528
+ end
529
+
530
+ ptr
531
+ end
532
+
533
+ # from a Ruby function get a pointer to some value.
534
+ def from_ruby_object arg
535
+ return "StringValueCStr(#{arg})" if @type.char?
536
+ arg
537
+ end
538
+
539
+ def to_ruby_object arg
540
+ return "rb_str_new2(#{arg})" if @type.char?
541
+ arg
542
+ end
543
+
544
+ def <=> other
545
+ return -1
546
+ end
547
+ end
548
+
549
+ class Boolean < RubyObject
550
+ include Helpers
551
+
552
+ def bool?; true; end
553
+ end
554
+
555
+ class TrueType < Boolean; end
556
+
557
+ class FalseType < Boolean; end
558
+
559
+ class NilType < RubyObject
560
+ def nil_type?; true; end
561
+ end
562
+
563
+ class CStructOrUnion
564
+ include Helpers
565
+ attr_reader :kind, :name, :c_name, :scope
566
+
567
+ def initialize kind, name, c_name, scope
568
+ @kind, @name, @c_name, @scope = kind, name, c_name, scope
569
+ end
570
+
571
+ def struct_or_union?; true; end
572
+
573
+ def to_s; "#{@c_name}"; end
13
574
  end
575
+
576
+ # FIXME: Find out a better way to generically find the old type of a typedef
577
+ # when the new type is encountered. Should cover cases where the new type
578
+ # is aliased with some other name too. In other words, reach the actual
579
+ # type in the most generic way possible without too many checks.
580
+ class TypeDef
581
+ # include Helpers
582
+ attr_reader :type, :old_type, :new_type
583
+
584
+ def initialize old_type, new_type, type
585
+ @old_type, @new_type, @type = old_type, new_type, type
586
+ end
587
+
588
+ def alias_type?; true; end
589
+
590
+ def to_s
591
+ @new_type.to_s
592
+ end
593
+
594
+ def base_type
595
+ @old_type
596
+ end
597
+
598
+ def method_missing meth, *args, &block
599
+ @old_type.send(meth, *args, &block)
600
+ end
601
+ end
602
+
603
+ class CStr
604
+ include Helpers
605
+
606
+ def cstr?; true; end
607
+
608
+ def p_formatter; "%s"; end
609
+
610
+ def from_ruby_object arg
611
+ "StringValueCStr(#{arg})"
612
+ end
613
+
614
+ def to_ruby_object arg
615
+ "rb_str_new_cstr(#{arg})"
616
+ end
617
+ end
618
+
619
+ class RubyConstant < RubyObject
620
+ attr_reader :name, :type
621
+
622
+ def initialize name
623
+ @name = name
624
+ # FIXME: make this flexible so that consts set to primitive types can be
625
+ # easily converted to C types.
626
+ @type = RubyObject.new
627
+ end
628
+
629
+ def ruby_constant?; true; end
630
+ end
631
+
632
+ class RubyClass < RubyConstant
633
+ attr_reader :name, :c_name, :scope, :ancestor
634
+
635
+ def initialize name, c_name, scope, ancestor
636
+ @name, @c_name, @scope, @ancestor = name, c_name, scope, ancestor
637
+ end
638
+
639
+ def ruby_class?; true; end
640
+ end
641
+
642
+ class RubyMethod
643
+ include Helpers
644
+
645
+ attr_reader :name, :c_name, :type
646
+ attr_accessor :scope, :arg_list
647
+
648
+ def initialize name, c_name, scope, arg_list
649
+ @name, @c_name, @scope, @arg_list = name, c_name, scope, arg_list
650
+ @type = RubyObject.new
651
+ end
652
+
653
+ def ruby_method?; true; end
654
+ end
655
+
656
+ class CFunction
657
+ include Helpers
658
+ attr_reader :name, :type, :c_name
659
+ attr_accessor :scope, :arg_list
660
+
661
+ # FIXME: all attributes should be initialized upon class creation to maintain
662
+ # sanity and consistency.
663
+ def initialize name, c_name, arg_list, type, scope
664
+ @name, @c_name, @arg_list, @type, @scope = name, c_name, arg_list, type, scope
665
+ end
666
+
667
+ def c_function?; true; end
668
+ end
669
+ # TODO: How to store this in a Ruby class? Use BigDecimal?
670
+ # class LF64
671
+ # def to_s; "long double"; end
672
+
673
+ # def to_ruby_object(arg); "INT2NUM"; end
674
+
675
+ # def from_ruby_object(arg); "(int32_t)NUM2INT"; end
676
+ # end
14
677
  end
15
- end
678
+ end