rubex 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/CONTRIBUTING.md +73 -9
  4. data/HISTORY.md +19 -0
  5. data/README.md +53 -8
  6. data/REFERENCE.md +112 -44
  7. data/benchmarks/no_gil/no_gil.rb +24 -0
  8. data/benchmarks/no_gil/no_gil.rubex +22 -0
  9. data/bin/rubex +1 -1
  10. data/examples/c_struct_interface/c_struct_interface.rubex +1 -0
  11. data/lib/rubex.rb +1 -0
  12. data/lib/rubex/ast.rb +11 -7
  13. data/lib/rubex/ast/expression.rb +1 -1
  14. data/lib/rubex/ast/expression/actual_arg_list.rb +7 -0
  15. data/lib/rubex/ast/expression/analysed_element_ref/c_var_element_ref.rb +5 -2
  16. data/lib/rubex/ast/expression/analysed_element_ref/ruby_object_element_ref.rb +26 -9
  17. data/lib/rubex/ast/expression/binary/binary_boolean.rb +1 -1
  18. data/lib/rubex/ast/expression/binary/binary_expo.rb +34 -0
  19. data/lib/rubex/ast/expression/binary/colon2.rb +34 -0
  20. data/lib/rubex/ast/expression/binary/empty_classes.rb +0 -3
  21. data/lib/rubex/ast/expression/command_call.rb +24 -0
  22. data/lib/rubex/ast/{statement → expression/command_call}/print.rb +4 -5
  23. data/lib/rubex/ast/{statement → expression/command_call}/raise.rb +29 -24
  24. data/lib/rubex/ast/expression/command_call/require.rb +27 -0
  25. data/lib/rubex/ast/expression/command_call/yield.rb +36 -0
  26. data/lib/rubex/ast/expression/element_ref.rb +10 -5
  27. data/lib/rubex/ast/expression/instance_var.rb +33 -0
  28. data/lib/rubex/ast/expression/method_call.rb +4 -2
  29. data/lib/rubex/ast/expression/method_call/c_function_call.rb +4 -3
  30. data/lib/rubex/ast/expression/method_call/ruby_method_call.rb +7 -5
  31. data/lib/rubex/ast/expression/name.rb +10 -1
  32. data/lib/rubex/ast/expression/ruby_object_element_ref/ruby_array_element_ref.rb +5 -2
  33. data/lib/rubex/ast/expression/ruby_object_element_ref/ruby_hash_element_ref.rb +10 -2
  34. data/lib/rubex/ast/expression/to_ruby_object.rb +1 -0
  35. data/lib/rubex/ast/expression/unary.rb +7 -3
  36. data/lib/rubex/ast/expression/unary_base/ampersand.rb +5 -0
  37. data/lib/rubex/ast/node.rb +213 -185
  38. data/lib/rubex/ast/node/file_node.rb +25 -0
  39. data/lib/rubex/ast/node/main_node.rb +56 -0
  40. data/lib/rubex/ast/statement/begin_block/begin.rb +4 -3
  41. data/lib/rubex/ast/statement/c_array_decl.rb +1 -1
  42. data/lib/rubex/ast/statement/c_ptr_decl.rb +2 -0
  43. data/lib/rubex/ast/statement/no_gil_block.rb +70 -0
  44. data/lib/rubex/ast/statement/return.rb +1 -0
  45. data/lib/rubex/ast/top_statement.rb +1 -1
  46. data/lib/rubex/ast/top_statement/klass.rb +4 -0
  47. data/lib/rubex/ast/top_statement/klass/attached_klass.rb +88 -10
  48. data/lib/rubex/ast/top_statement/method_def.rb +2 -3
  49. data/lib/rubex/ast/top_statement/method_def/c_function_def.rb +10 -4
  50. data/lib/rubex/cli.rb +11 -6
  51. data/lib/rubex/code_supervisor.rb +49 -0
  52. data/lib/rubex/code_writer.rb +22 -1
  53. data/lib/rubex/compiler.rb +109 -30
  54. data/lib/rubex/compiler_config.rb +14 -1
  55. data/lib/rubex/constants.rb +3 -0
  56. data/lib/rubex/data_type.rb +2 -3
  57. data/lib/rubex/data_type/ruby_object/ruby_symbol.rb +0 -1
  58. data/lib/rubex/error.rb +4 -0
  59. data/lib/rubex/helpers/writers.rb +33 -4
  60. data/lib/rubex/lexer.rex +9 -1
  61. data/lib/rubex/lexer.rex.rb +15 -2
  62. data/lib/rubex/parser.racc +125 -49
  63. data/lib/rubex/parser.racc.rb +1526 -1376
  64. data/lib/rubex/rake_task.rb +42 -6
  65. data/lib/rubex/symbol_table/entry.rb +6 -0
  66. data/lib/rubex/symbol_table/scope.rb +28 -3
  67. data/lib/rubex/version.rb +1 -1
  68. data/rubex.gemspec +1 -0
  69. data/spec/basic_ruby_method_spec.rb +2 -2
  70. data/spec/blocks_spec.rb +2 -2
  71. data/spec/box_op_multi_args_spec.rb +34 -0
  72. data/spec/c_function_ptrs_spec.rb +2 -2
  73. data/spec/c_functions_spec.rb +2 -0
  74. data/spec/c_struct_interface_spec.rb +8 -3
  75. data/spec/default_args_spec.rb +2 -2
  76. data/spec/external_c_struct_spec.rb +33 -0
  77. data/spec/fixtures/api/consumer.rubex +0 -0
  78. data/spec/fixtures/api/implementation.rubex +0 -0
  79. data/spec/fixtures/api/implementation.rubexd +0 -0
  80. data/spec/fixtures/box_op_multi_args/box_op_multi_args.rubex +3 -0
  81. data/spec/fixtures/c_functions/c_functions.rubex +13 -0
  82. data/spec/fixtures/c_struct_interface/c_struct_interface.rubex +28 -0
  83. data/spec/fixtures/class_methods/class_methods.rubex +1 -1
  84. data/spec/fixtures/error_handling/error_handling.rubex +2 -2
  85. data/spec/fixtures/external_c_struct/external_c_struct.rubex +16 -0
  86. data/spec/fixtures/if_else/if_else.rubex +1 -1
  87. data/spec/fixtures/init_ruby_objects_with_literal_syntax/init_ruby_objects_with_literal_syntax.rubex +1 -1
  88. data/spec/fixtures/instance_variables/instance_variables.rubex +25 -0
  89. data/spec/fixtures/loops/loops.rubex +2 -2
  90. data/spec/fixtures/module/module.rubex +28 -0
  91. data/spec/fixtures/multi_file_programs/Rakefile +8 -0
  92. data/spec/fixtures/multi_file_programs/a.rubex +5 -0
  93. data/spec/fixtures/multi_file_programs/b.rubex +5 -0
  94. data/spec/fixtures/multi_file_programs/multi_file_programs.rubex +14 -0
  95. data/spec/fixtures/no_gil/no_gil.rubex +24 -0
  96. data/spec/fixtures/no_gil_attach_class/no_gil_attach_class.rubex +23 -0
  97. data/spec/fixtures/no_gil_compile_check/no_gil_compile_check.rubex +4 -0
  98. data/spec/fixtures/outside_stmts/outside_stmts.rubex +6 -0
  99. data/spec/fixtures/pow/pow.rubex +4 -0
  100. data/spec/fixtures/rake_task/single_file/test.rubex +3 -0
  101. data/spec/fixtures/recursion/recursion.rubex +1 -1
  102. data/spec/fixtures/ruby_constant_scoping/ruby_constant_scoping.rubex +7 -0
  103. data/spec/fixtures/ruby_operators/ruby_operators.rubex +1 -1
  104. data/spec/fixtures/ruby_raise/ruby_raise.rubex +2 -2
  105. data/spec/fixtures/ruby_types/ruby_types.rubex +4 -4
  106. data/spec/fixtures/statement_expression/statement_expression.rubex +2 -2
  107. data/spec/fixtures/static_array/static_array.rubex +3 -3
  108. data/spec/fixtures/string_literals/string_literals.rubex +12 -2
  109. data/spec/fixtures/struct/struct.rubex +1 -1
  110. data/spec/fixtures/var_declarations/var_declarations.rubex +1 -1
  111. data/spec/implicit_lib_include_spec.rb +2 -2
  112. data/spec/init_ruby_objects_with_literal_syntax_spec.rb +2 -2
  113. data/spec/instance_variables_spec.rb +33 -0
  114. data/spec/loops_spec.rb +2 -2
  115. data/spec/module_spec.rb +39 -0
  116. data/spec/multi_file_programs_spec.rb +41 -0
  117. data/spec/no_gil_attach_class_spec.rb +33 -0
  118. data/spec/no_gil_compile_check_spec.rb +25 -0
  119. data/spec/no_gil_spec.rb +36 -0
  120. data/spec/outside_stmts_spec.rb +34 -0
  121. data/spec/pow_spec.rb +33 -0
  122. data/spec/rake_task_spec.rb +142 -0
  123. data/spec/recursion_spec.rb +4 -4
  124. data/spec/ruby_constant_scoping_spec.rb +42 -0
  125. data/spec/ruby_raise_spec.rb +2 -2
  126. data/spec/ruby_symbols_spec.rb +2 -2
  127. data/spec/ruby_types_spec.rb +2 -2
  128. data/spec/spec_helper.rb +17 -3
  129. data/spec/string_literals_spec.rb +1 -0
  130. metadata +90 -6
  131. data/lib/rubex/ast/statement/yield.rb +0 -41
@@ -2,25 +2,30 @@ require 'thor'
2
2
  module Rubex
3
3
  # Cli for rubex using Thor(http://whatisthor.com/)
4
4
  class Cli < Thor
5
- desc 'generate FILE', 'generates directory with name specified in the argument and creates an extconf.rb file which is required for C extensions'
5
+
6
+ desc 'generate FILE',
7
+ 'generates directory with name specified in the argument and creates an extconf.rb file which is required for C extensions'
6
8
  option :force, aliases: '-f', desc: 'replace existing files and directories'
7
9
  option :dir, aliases: '-d', desc: 'specify a directory for generating files', type: :string
8
- option :install, aliases: '-i', desc: 'automatically run install command after generating Makefile'
10
+ option :install, aliases: '-i',
11
+ desc: 'automatically run install command after generating Makefile'
9
12
  option :debug, aliases: '-g', desc: 'enable debugging symbols when compiling with GCC'
10
13
  def generate(file)
11
14
  if (force = options[:force])
12
- directory = (options[:dir] ? options[:dir].to_s : Dir.pwd) + "/#{Rubex::Compiler.extract_target_name(file)}"
15
+ directory = (options[:dir] ? options[:dir].to_s : Dir.pwd) +
16
+ "/#{Rubex::Compiler.extract_target_name(file)}"
13
17
  STDOUT.puts "Warning! you are about to replace contents in the directory '#{directory}', Are you sure? [Yn] "
14
18
  confirmation = STDIN.gets.chomp
15
19
  force = (confirmation == 'Y')
16
20
  end
17
- Rubex::Compiler.compile file, directory: options[:dir], force: force, make: options[:install], debug: options[:debug]
21
+ Rubex::Compiler.compile file, target_dir: options[:dir], force: force,
22
+ make: options[:install], debug: options[:debug]
18
23
  end
19
24
 
20
- desc 'install PATH', 'run "make" utility to generate a shared object file required for C extensions'
25
+ desc 'install PATH',
26
+ 'run "make" utility to generate a shared object file required for C extensions'
21
27
  def install(path)
22
28
  Rubex::Compiler.run_make path
23
29
  end
24
-
25
30
  end
26
31
  end
@@ -0,0 +1,49 @@
1
+ module Rubex
2
+ # Class for storing Rubex files and their corresponding code writer objects.
3
+ # Each file has two code writers - header_writer and code_writer. The
4
+ # header_writer stores the file header of the outputted C code (the .h file)
5
+ # and the code_writer stores the actual implementation (the .c file).
6
+ #
7
+ # It is created only once in the execution of the compiler by the Compiler class.
8
+ # Data is stored in the @data class in the form:
9
+ # @data = {
10
+ # "file1.rubex" => {
11
+ # header: header_writer, # Rubex::CodeWriter instance.
12
+ # code: code_writer, # Rubex:: CodeWriter instance.
13
+ # },
14
+ # "file2.rubex" => {
15
+ # header: header_writer, # Rubex::CodeWriter instance.
16
+ # code: code_writer, # Rubex:: CodeWriter instance.
17
+ # }
18
+ # }
19
+ class CodeSupervisor
20
+ def initialize
21
+ @data = {}
22
+ end
23
+
24
+ def init_file(file_name)
25
+ header_writer = Rubex::CodeWriter.new(file_name, is_header: true)
26
+ header_writer << "/*Header file for #{file_name}*/\n\n"
27
+
28
+ code_writer = Rubex::CodeWriter.new(file_name)
29
+ code_writer << "/*Code file for #{file_name}*/\n\n"
30
+
31
+ @data[file_name] = {
32
+ header: header_writer,
33
+ code: code_writer
34
+ }
35
+ end
36
+
37
+ def header(file_name)
38
+ @data[file_name][:header]
39
+ end
40
+
41
+ def code(file_name)
42
+ @data[file_name][:code]
43
+ end
44
+
45
+ def files
46
+ @data.keys
47
+ end
48
+ end
49
+ end
@@ -2,12 +2,28 @@ module Rubex
2
2
  class CodeWriter
3
3
  attr_reader :code
4
4
 
5
- def initialize target_name
5
+ def initialize target_name, is_header: false
6
6
  @code = "/* C extension for #{target_name}.\n"\
7
7
  "This file in generated by Rubex::Compiler. Do not change!\n"\
8
8
  "File generation time: #{Time.now}."\
9
9
  "*/\n\n"
10
10
  @indent = 0
11
+ @is_header = is_header
12
+ end
13
+
14
+ def header?
15
+ @is_header
16
+ end
17
+
18
+ def in_header_guard guard, &block
19
+ if header?
20
+ @code << "#ifndef #{guard}\n"
21
+ @code << "#define #{guard}\n"
22
+ block.call
23
+ @code << "#endif\n"
24
+ else
25
+ raise "file is not a header file."
26
+ end
11
27
  end
12
28
 
13
29
  # type - Return type of the method.
@@ -19,6 +35,11 @@ module Rubex
19
35
  new_line
20
36
  end
21
37
 
38
+ def write_include file_name
39
+ @code << "#include \"#{file_name}.h\""
40
+ new_line
41
+ end
42
+
22
43
  def colon
23
44
  @code << ";"
24
45
  new_line
@@ -4,24 +4,73 @@ module Rubex
4
4
  CONFIG = Rubex::CompilerConfig.new
5
5
 
6
6
  class << self
7
- def compile path, test: false, directory: nil, force: false, make: false, debug: false
8
- tree = ast path, test: test
9
- target_name = extract_target_name path
10
- code = generate_code tree, target_name
11
- ext = extconf target_name, directory: directory
7
+ # Compile the Rubex file(s) into .c file(s). Do not use this function directly
8
+ # unless you're contributing to Rubex. Use the Rake tasks or command line
9
+ # interface instead.
10
+ #
11
+ # @param path [String] Full path to file. Main file in case of multiple
12
+ # file compilation.
13
+ # @param test [Boolean] false Set to true if compiling rubex files for
14
+ # a test case.
15
+ # @param multi_file [Boolean] false If true, return the CodeSupervisor
16
+ # object for code analysis by user. Applicable only if test: opt is true.
17
+ # @param directory [String] nil Directory where the compiled rubex files
18
+ # should be placed.
19
+ # @param force [Boolean] false If set to true, will forcefully overwrite
20
+ # any .c files that were previously generated.
21
+ # @param make [Boolean] false If true, will automatically generate the .so
22
+ # file from compiled C binaries.
23
+ # @param debug [Boolean] false If true, will compile C programs with gcc
24
+ # using the -g option.
25
+ # @param source_dir [String] nil String specifying the source directory
26
+ # inside which the source Rubex files will be placed in case of multi-file
27
+ # programs.
28
+ # @param files [Array[String]] nil An Array specifying the file names to
29
+ # compile w.r.t the source_dir directory.
30
+ #
31
+ # TODO: The path can be relative to the source_dir if source_dir is specified.
32
+ def compile path,
33
+ test: false,
34
+ multi_file: false,
35
+ target_dir: nil,
36
+ force: false,
37
+ make: false,
38
+ debug: false,
39
+ source_dir: nil,
40
+ files: nil
12
41
  CONFIG.flush
13
42
  CONFIG.debug = debug
14
-
15
- return [tree, code, ext] if test
16
- write_files target_name, code, ext, directory: directory, force: force
17
- full_path = build_path(directory, target_name)
43
+ CONFIG.add_link "m" # link cmath libraries
44
+ target_name = extract_target_name path
45
+ CONFIG.add_dep target_name
46
+
47
+ tree = ast path, source_dir: source_dir, test: test
48
+ supervisor = generate_code tree, target_name
49
+ ext = extconf target_name, target_dir: target_dir
50
+
51
+ if test && !multi_file
52
+ return [tree, supervisor.code(target_name), ext,
53
+ supervisor.header(target_name)]
54
+ elsif test && multi_file
55
+ return [tree, supervisor, ext]
56
+ end
57
+ write_files target_name, supervisor, ext, target_dir: target_dir, force: force
58
+ full_path = build_path(target_dir, target_name)
18
59
  load_extconf full_path
19
60
  run_make full_path if make
20
61
  end
21
62
 
22
- def ast path, test: false
63
+ # Generate the AST from Rubex source code. Do not use this function unless
64
+ # contributing to Rubex. Use CLI or rake tasks instead.
65
+ #
66
+ # @param path [String] Full path name of the rubex file.
67
+ # @param test [Boolean] false Set to true if compiling rubex files for
68
+ # a test case.
69
+ # @param source_dir [String] nil Path of the directory that contains the
70
+ # source files.
71
+ def ast path, test: false, source_dir: nil
23
72
  parser = Rubex::Parser.new
24
- parser.parse(path)
73
+ parser.parse(path, source_dir, false)
25
74
  parser.do_parse
26
75
  rescue Racc::ParseError => e
27
76
  raise e if test
@@ -33,40 +82,57 @@ module Rubex
33
82
  STDERR.puts error_msg
34
83
  end
35
84
 
36
- def extconf target_name, directory: nil
37
- path = build_path(directory, target_name)
85
+ def extconf target_name, target_dir: nil
86
+ path = build_path(target_dir, target_name)
38
87
  extconf = ""
39
88
  extconf << "require 'mkmf'\n"
40
89
  extconf << "$libs += \" #{CONFIG.link_flags}\"\n"
41
90
  extconf << "$CFLAGS += \" -g \"\n" if CONFIG.debug
91
+
92
+ srcs_config = CONFIG.srcs.map { |s| "\"#{s}\""}.join(',')
93
+ extconf << "$srcs = [#{srcs_config}]\n"
94
+
95
+ objs_config = CONFIG.objs.map { |o| "\"#{o}\""}.join(',')
96
+ extconf << "$objs = [#{objs_config}]\n"
97
+
42
98
  extconf << "create_makefile('#{path}/#{target_name}')\n"
43
99
  extconf
44
100
  end
45
101
 
46
102
  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
103
+ supervisor = Rubex::CodeSupervisor.new
104
+ supervisor.init_file(target_name)
105
+ raise "Must be a Rubex::AST::Node::MainNode, not #{tree.class}" unless
106
+ tree.is_a? Rubex::AST::Node::MainNode
107
+ tree.process_statements target_name, supervisor
108
+ supervisor
52
109
  end
53
110
 
54
111
  def extract_target_name path
55
112
  File.basename(path).split('.')[0]
56
113
  end
57
114
 
58
- def write_files target_name, code, ext, directory: nil, force: false
59
- path = build_path(directory, target_name)
115
+ # Write .c and .h files from the generated C code from rubex files.
116
+ #
117
+ # @param target_name [String] Target name of the root file.
118
+ # @param supervisor [Rubex::CodeSupervisor] Container for code.
119
+ # @param ext [String] A String representing the extconf file.
120
+ # @param directory [String] nil Target directory in which files are to be placed.
121
+ # @param force [Boolean] false Recreate the target directory and rewrite the
122
+ # files whether they are already present or not.
123
+ def write_files target_name, supervisor, ext, target_dir: nil, force: false
124
+ path = build_path(target_dir, target_name)
60
125
  FileUtils.rm_rf(path) if force && Dir.exist?(path)
61
126
  Dir.mkdir(path) unless Dir.exist?(path)
62
127
 
63
- code_file = File.new "#{path}/#{target_name}.c", "w+"
64
- code_file.puts code.to_s
65
- code_file.close
66
-
67
- extconf_file = File.new "#{path}/extconf.rb", "w+"
68
- extconf_file.puts ext
69
- extconf_file.close
128
+ write_to_file "#{path}/#{Rubex::COMMON_UTILS_FILE}.h",
129
+ supervisor.header(Rubex::COMMON_UTILS_FILE).to_s
130
+ supervisor.files.each do |file|
131
+ write_to_file "#{path}/#{file}.c", supervisor.code(file).to_s
132
+ write_to_file "#{path}/#{file}.h", supervisor.header(file).to_s
133
+ end
134
+
135
+ write_to_file "#{path}/extconf.rb", ext
70
136
  end
71
137
 
72
138
  def load_extconf path
@@ -81,13 +147,26 @@ module Rubex
81
147
  end
82
148
  end
83
149
 
150
+ # Create build path for outputting .c and .h files. Will check whether the calling
151
+ # process is a rake task or cmd.
152
+ #
153
+ # @param directory [String] The directory inside which this build path will exist.
154
+ # @param target_name [String] Name of the folder inside the directory.
84
155
  def build_path directory, target_name
85
156
  directory = (directory ? directory.to_s : Dir.pwd)
86
- unless directory.end_with?(target_name)
87
- directory += "/#{target_name}"
88
- end
157
+ unless directory.end_with?(target_name)
158
+ directory += "/#{target_name}"
159
+ end
89
160
  directory
90
161
  end
162
+
163
+ private
164
+
165
+ def write_to_file path, contents
166
+ f = File.new path, "w+"
167
+ f.puts contents
168
+ f.close
169
+ end
91
170
  end
92
171
  end
93
172
  end
@@ -1,9 +1,14 @@
1
1
  module Rubex
2
+ # Class for storing configuration of the compiler (gcc) that will compile
3
+ # the generated C code. This includes file names, compiler flags and other
4
+ # options required by Rubex.
2
5
  class CompilerConfig
3
- attr_accessor :debug
6
+ attr_accessor :debug, :srcs, :objs
4
7
 
5
8
  def initialize
6
9
  @links = []
10
+ @srcs = []
11
+ @objs = []
7
12
  end
8
13
 
9
14
  def add_link link_str
@@ -16,6 +21,14 @@ module Rubex
16
21
 
17
22
  def flush
18
23
  @links = []
24
+ @srcs = []
25
+ @objs = []
26
+ end
27
+
28
+ # add dependency on file so extconf will recognise it.
29
+ def add_dep(file_name)
30
+ @srcs << "#{file_name}.c"
31
+ @objs << "#{file_name}.o"
19
32
  end
20
33
  end
21
34
  end
@@ -15,6 +15,9 @@ module Rubex
15
15
 
16
16
  ACTUAL_ARGS_SUFFIX = "_actual_args"
17
17
 
18
+ COMMON_UTILS_CONST = RUBEX_PREFIX + "_COMMON_UTILS_H"
19
+ COMMON_UTILS_FILE = RUBEX_PREFIX + "_common_utils_"
20
+
18
21
  TYPE_MAPPINGS = {
19
22
  'char' => Rubex::DataType::Char,
20
23
  'bool' => Rubex::DataType::CBoolean,
@@ -1,7 +1,6 @@
1
1
  require_relative 'data_type_helpers/helpers'
2
- Dir['./lib/rubex/data_type_helpers/**/*.rb'].sort.each { |f| require f }
3
- Dir['./lib/rubex/data_type/**/*.rb'].sort.each { |f| require f }
4
-
2
+ Dir[File.join(File.dirname(File.dirname(__FILE__)), "rubex", "data_type_helpers", "**", "*.rb" )].sort.each { |f| require f }
3
+ Dir[File.join(File.dirname(File.dirname(__FILE__)), "rubex", "data_type", "**", "*.rb" )].sort.each { |f| require f }
5
4
  # TODO: How to store this in a Ruby class? Use BigDecimal?
6
5
  # class LF64
7
6
  # def to_s; "long double"; end
@@ -5,6 +5,5 @@ module Rubex
5
5
  true
6
6
  end
7
7
  end
8
-
9
8
  end
10
9
  end
@@ -12,4 +12,8 @@ module Rubex
12
12
  class TypeError < StandardError; end
13
13
 
14
14
  class LibraryNotFoundError < StandardError; end
15
+
16
+ class CompileCheckError < StandardError; end
17
+
18
+ class FileNotFoundError < StandardError; end
15
19
  end
@@ -29,9 +29,8 @@ module Rubex
29
29
  end
30
30
  end
31
31
 
32
- def declare_types(code, scope)
33
- scope.type_entries.each do |entry|
34
- # if !entry.extern
32
+ def declare_types(code, type_entries)
33
+ type_entries.each do |entry|
35
34
  type = entry.type
36
35
 
37
36
  if type.alias_type?
@@ -54,7 +53,6 @@ module Rubex
54
53
  end
55
54
  end
56
55
  code.nl
57
- # end
58
56
  end
59
57
  end
60
58
 
@@ -74,6 +72,37 @@ module Rubex
74
72
  code.declare_variable type: var.type.to_s, c_name: var.c_name
75
73
  end
76
74
  end
75
+
76
+ def write_usability_macros(code)
77
+ code.nl
78
+ code.c_macro Rubex::RUBEX_PREFIX + 'INT2BOOL(arg) (arg ? Qtrue : Qfalse)'
79
+ code.nl
80
+ end
81
+
82
+ def write_usability_functions_header(header)
83
+ header.nl
84
+ write_char_2_ruby_str_header header
85
+ end
86
+
87
+ def write_usability_functions_code(code)
88
+ code.nl
89
+ write_char_2_ruby_str_code(code)
90
+ end
91
+
92
+ def write_char_2_ruby_str_header(header)
93
+ header.nl
94
+ header << "VALUE #{Rubex::C_FUNC_CHAR2RUBYSTR}(char ch);"
95
+ end
96
+
97
+ def write_char_2_ruby_str_code(code)
98
+ code << "VALUE #{Rubex::C_FUNC_CHAR2RUBYSTR}(char ch)"
99
+ code.block do
100
+ code << "char s[2];\n"
101
+ code << "s[0] = ch;\n"
102
+ code << "s[1] = '\\0';\n"
103
+ code << "return rb_str_new2(s);\n"
104
+ end
105
+ end
77
106
  end
78
107
  end
79
108
  end
@@ -29,8 +29,11 @@ macros
29
29
  NULL /NULL/
30
30
  ATTACH /attach/
31
31
  BLOCK_GIVEN /block_given\?/
32
+ NO_GIL /no_gil/
33
+ REQUIRE_RUBEX /require_rubex/
32
34
 
33
35
  IDENTIFIER /[a-zA-Z_][a-zA-Z_0-9]*/
36
+ COLON2 /::/
34
37
  LPAREN /\(/
35
38
  RPAREN /\)/
36
39
  LSQUARE /\[/
@@ -126,6 +129,7 @@ rules
126
129
  # Method hacks
127
130
 
128
131
  /data\$/ { [:kDATA_VAR, text] }
132
+ /#{REQUIRE_RUBEX}/ { [:kREQUIRE_RUBEX, text] }
129
133
  /#{DOT}#{EACH}/ { [:kDOT_EACH, text] }
130
134
 
131
135
  # Data Types
@@ -144,8 +148,10 @@ rules
144
148
  /#{STRUCT}\ / { [:kSTRUCT, text] }
145
149
  /#{UNION}\ / { [:kUNION, text] }
146
150
  /#{ALIAS}\ / { [:kALIAS, text] }
151
+ /#{NO_GIL}/ { [:kNO_GIL, text] }
147
152
 
148
153
  /:#{IDENTIFIER}/ { [:tSYMBOL, text] }
154
+ /@#{IDENTIFIER}/ { [:tINSTANCE_VAR, text] }
149
155
  /#{IDENTIFIER}/ { [:tIDENTIFIER, text] }
150
156
  /#{LBRACE}/ { [:tLBRACE, text] }
151
157
  /#{RBRACE}/ { [:tRBRACE, text] }
@@ -158,21 +164,23 @@ rules
158
164
  /#{NL}/ { [:tNL, text] }
159
165
  /#{QMARK}/ { [:tQMARK, text]}
160
166
  /#{DOT}/ { [:tDOT, text] }
167
+ /#{COLON2}/ { [:tCOLON2, text] }
161
168
  /#{COLON}/ { [:tCOLON, text] }
162
169
 
163
170
  # operators
164
171
 
172
+ /#{EXPOASSIGN}/ { [:tOP_ASSIGN, text]}
165
173
  /#{PLUSASSIGN}/ { [:tOP_ASSIGN, text]}
166
174
  /#{MINUSASSIGN}/ { [:tOP_ASSIGN, text]}
167
175
  /#{STARASSIGN}/ { [:tOP_ASSIGN, text]}
168
176
  /#{DIVIDEASSIGN}/ { [:tOP_ASSIGN, text]}
169
177
  /#{EXPOASSIGN}/ { [:tOP_ASSIGN, text]}
170
178
  /#{MODULUSASSIGN}/ { [:tOP_ASSIGN, text]}
179
+ /#{EXPO}/ { [:tEXPO, text]}
171
180
  /#{PLUS}/ { [:tPLUS, text]}
172
181
  /#{MINUS}/ { [:tMINUS, text]}
173
182
  /#{STAR}/ { [:tSTAR, text]}
174
183
  /#{DIVIDE}/ { [:tDIVIDE, text]}
175
- /#{EXPO}/ { [:tEXPO, text]}
176
184
  /#{MODULUS}/ { [:tMODULUS, text]}
177
185
  /#{EXPO}/ { [:tEXPO, text]}
178
186
  /#{EQ}/ { [:tEQ, text] }