rubex 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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] }