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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 742568f609bbfd393f0262b1f8b79089a3e22007053e72714bbb8cc256fd5066
4
- data.tar.gz: 7bd08df3a97cdf480bdb4fa5b34ef37553678f97cbd19f53027296148724c66a
2
+ SHA1:
3
+ metadata.gz: c8859787757dadc4f2cadd8cbb2d227d26ae5f69
4
+ data.tar.gz: bb028214cc70f7fee50d0fd0c185bd89244eb593
5
5
  SHA512:
6
- metadata.gz: 32b17fb06897cf4ca018dd61ba27ee58b6f21d885b715c7ab13effd726175465379912c168c21ba0a7ba48ee69f244996fbb680ae5a33a78021cd07745b6473f
7
- data.tar.gz: febfc14a8dabb0ab050d592f9d50cfeaaf068007cb0635104876cfa679710fd311e4e71d38f4f8cf3019a6ef78e231fa4638381803899e3f4ee499f19312d41c
6
+ metadata.gz: 71322d0c3be4a0acedfa74d11789941c43f5cd81613bd771445f6124e48fa84b22bbdb451de731bdc15df1a534715e1628debdc10334cb468773c584bb992746
7
+ data.tar.gz: 1ec819863e026a14283dfb0d0ffde57df6d29457cb72561f816cc6aa840d29fe01947a1e705550205b5dff30806f1c12873653917ffa1780a9425408dd772d58
data/.gitignore CHANGED
@@ -53,3 +53,4 @@ lib/rubex/parser.output
53
53
  lib/rubex/parser.tab.rb
54
54
  /.idea/
55
55
  TAGS
56
+ parse.y
@@ -31,14 +31,66 @@ Couple of conventions that I followed when writing the code:
31
31
  - analyse_statement(local_scope)
32
32
  - generate_code(code, local_scope)
33
33
  * Expressions contain methods:
34
- - analyse_statement(local_scope)
34
+ - analyse_types(local_scope)
35
35
  - c_code(local_scope)
36
36
 
37
- Sometimes it can so happen that an expression can consist simply of a single variable (like `if (a)`) or be a full expression (like `if (a == b)`). In the first case, the `a` is just read as an `IDENTIFIER` by the parser. In the second case, `a == b` is read as an `expr` and is stored in the AST as `Rubex::AST::Expression`.
38
-
39
- Now you might be thinking why expressions should also have a `analyse_statement` method, that's just for maintaining uniformity between exprs and stmts (maybe that should be just `analyse`?).
40
-
41
- When writing the `<=>` operator under Rubex::DataType classes, I have been forced to assume that `Int` is 32 bits long since I have not yet incorporated a way to figure out the number of bits used by a particular machine for representing an `int`. It will be changed later to make it machine-dependent.
37
+ Sometimes it can so happen that an expression can consist simply of a single variable
38
+ (like `if (a)`) or be a full expression (like `if (a == b)`). In the first case, the
39
+ `a` is just read as an `IDENTIFIER` by the parser. In the second case, `a == b` is
40
+ read as an `expr` and is stored in the AST as `Rubex::AST::Expression`.
41
+
42
+ When writing the `<=>` operator under Rubex::DataType classes, I have been forced to
43
+ assume that `Int` is 32 bits long since I have not yet incorporated a way to figure
44
+ out the number of bits used by a particular machine for representing an `int`.
45
+ It will be changed later to make it machine-dependent.
46
+
47
+ ## Parser particulars
48
+
49
+ Kinds of statements that can be defined at the top:
50
+ * classes.
51
+ * attached classes.
52
+ * modules.
53
+ * ruby/c methods.
54
+ * all kinds of exprs. (command call/binary/unary etc.)
55
+ * if stmts.
56
+ * while.
57
+ * for.
58
+ * c bindings.
59
+ * function declaration.
60
+ * struct or union definition.
61
+ * alias statements.
62
+ * assignment statements.
63
+ * variable decl and init.
64
+ * forward declaration.
65
+
66
+ stmts that can be defined inside other classes:
67
+ * other classes.
68
+ * attached classes.
69
+ * modules.
70
+ * c functions.
71
+ * ruby methods.
72
+ * struct/union definitions.
73
+ * constants.
74
+ * class variables.
75
+ * attr reader/writer/accessor.
76
+ * forward declaration.
77
+
78
+ stmts that can be defined inside other functions/blocks:
79
+ * EVERYTHING _except_:
80
+ - classes.
81
+ - attached classes.
82
+ - modules.
83
+ - ruby/c methods.
84
+ - c bindinds.
85
+
86
+ ## Multi file programs
87
+
88
+ When specifying mutliple rubex files using rake tasks or the command line, rubex will read
89
+ the name of the main file, find the main file and start compiling that first. Whatever
90
+
91
+ Since above approach does not really require user to specify all the files at compile time,
92
+ the 'files' option is only useful when the user is only running the Rubex compiler and not
93
+ generating any binaries.
42
94
 
43
95
  # Important data representations
44
96
 
@@ -52,7 +104,8 @@ This consists of a hash that looks like this:
52
104
  }
53
105
  ```
54
106
 
55
- The `:variables` field might be `nil` in case of a function declaration in which case it is not necessary to specify the name of the variable.
107
+ The `:variables` field might be `nil` in case of a function declaration in which
108
+ case it is not necessary to specify the name of the variable.
56
109
 
57
110
  The `:variables` key maps to a value that is an Array of Hashes that contains a single Hash:
58
111
  ```
@@ -63,7 +116,8 @@ The `:variables` key maps to a value that is an Array of Hashes that contains a
63
116
  }
64
117
  ```
65
118
 
66
- `identity` can be a Hash in case of a function pointer argument, or a simple String in case its an identifier, or an `ElementRef` if specifying an array of elements.
119
+ `identity` can be a Hash in case of a function pointer argument, or a simple String in case
120
+ its an identifier, or an `ElementRef` if specifying an array of elements.
67
121
 
68
122
  If Hash, it will look like this:
69
123
  ```
@@ -78,13 +132,23 @@ If Hash, it will look like this:
78
132
 
79
133
  ## Attach classes
80
134
 
135
+ ## no_gil block code generation
81
136
 
137
+ The generated code for the `no_gil` block has the following components:
138
+ * a function that is namespaced according to the name of the scoping
139
+ function, class and number of no_gil blocks that occur in the function.
140
+ * all the statements that are present in the no_gil block are present in this function.
141
+ * all the variables that are present in the block are made global and are properly
142
+ namespaced accoring to above namespacing criteria.
143
+ * code appropriate for `rb_thread_call_without_gvl` is generated and a pointer to the
144
+ generated function is passed to the function.
145
+ * the new code using the `without_gvl` call is inserted in the place where the `no_gil`
146
+ block was present.
82
147
 
83
148
  # Future work
84
149
 
85
150
  The following features in Rubex need to be implemented or can be made better:
86
151
 
87
- * Ability to have Ruby-style method arguments without parenthesis.
88
152
  * Multiline conditionals in the condition of if-elsif statements.
89
153
  * Special treatment for VALUE C arrays by marking each element with GC.
90
154
  * Checks for return statement. No return statement or wrong return type should raise error/warning.
data/HISTORY.md CHANGED
@@ -1,3 +1,22 @@
1
+ # v0.1.2 (26 May 2018)
2
+
3
+ ## Bug fixes
4
+
5
+ * Fixed bug that prevented proper loading of files from CLI.
6
+
7
+ ## Features
8
+
9
+ * Added `no_gil` block support.
10
+ * Allow creating instance variables.
11
+ * Multiple file Rubex programs using `rubex_require`.
12
+ * Support multiple arguments in `[]` operator.
13
+ * New rake tasks for various options like debug, just compiling, compile + install etc.
14
+ * More CLI options for debug and force.
15
+
16
+ # v0.1.1
17
+
18
+ * Bugs fixes and internal code refactoring. Not much in terms of user-facing features.
19
+
1
20
  # v0.1 (17 Sept. 2017)
2
21
 
3
22
  * First release.
data/README.md CHANGED
@@ -118,19 +118,54 @@ Notice the only difference between the above Rubex code and Ruby is the specific
118
118
  Rubex also takes care of the initial setup and compilation of the C files, so all you need to do is execute a bunch of commands and your extension is up and running!
119
119
 
120
120
  # Installation
121
- To build, requires Ruby version >= 2.3.0
121
+ Requires Ruby version >= 2.3.0
122
122
 
123
- The gem as of now has not reached v0.1. However, you can try it out with:
123
+ Install with:
124
124
  ```
125
- git clone https://github.com/v0dro/rubex.git
126
- cd rubex
127
- bundle install
128
- rake install
125
+ gem install rubex
129
126
  ```
130
127
 
131
128
  # Usage
132
129
 
133
- Installing the gem will also install the `rubex` binary. You can now write a Rubex file (with a `.rubex` file extension) and compile it into C code with:
130
+ Installing the gem will also install the `rubex` binary. You can now write a Rubex file (with a `.rubex` file extension) and compile it into C code using the following commands.
131
+
132
+ ## Commands
133
+
134
+ #### Generate
135
+
136
+ Create all the necessary files for the C extension.
137
+
138
+ ```
139
+ rubex generate file_name.rubex
140
+ ```
141
+
142
+ ```
143
+ Options
144
+ -f, [--force] # replace existing files and directories
145
+ -d, [--dir=DIR] # specify a directory for generating files
146
+ -i, [--install] # automatically run install command after generating Makefile
147
+ -g, [--debug] # enable debugging symbols when compiling with GCC
148
+ ```
149
+
150
+ #### Install
151
+
152
+ Run the `make` utility on generated files.
153
+
154
+ ```
155
+ rubex install path/to/generated/directory
156
+ ```
157
+
158
+ #### Help
159
+
160
+ Describe available commands or one specific command
161
+
162
+ ```
163
+ rubex help [COMMAND]
164
+ ```
165
+
166
+ ## Manual Usage
167
+ If you want to manually generate the files, you can do that with:
168
+
134
169
  ```
135
170
  rubex file_name.rubex
136
171
  ```
@@ -150,6 +185,15 @@ Give yourself 5 min and go through the [TUTORIAL](TUTORIAL.md). Convert a part o
150
185
 
151
186
  Read the full Rubex reference in [REFERENCE](REFERENCE.md).
152
187
 
188
+ # Differences with Ruby
189
+
190
+ Although Rubex tries its best to support the Ruby syntax as much as possible, in some cases it is not feasible or necessary to provide full support. Following is a list of differences between Ruby and Rubex syntax:
191
+
192
+ * All methods in Rubex (including `require` calls) must use round brackets for arguments.
193
+ * No support Ruby blocks.
194
+ * No support for class variables.
195
+ * All methods and functions in Rubex must use the `return` statement for returning values.
196
+
153
197
  # Roadmap
154
198
 
155
199
  See the [CONTRIBUTING](CONTRIBUTING.md) and the GitHub issue tracker for future features.
@@ -157,5 +201,6 @@ See the [CONTRIBUTING](CONTRIBUTING.md) and the GitHub issue tracker for future
157
201
  # Acknowledgements
158
202
 
159
203
  * The Ruby Association (Japan) for providing the initial funding for this project through the Ruby Association Grant 2016.
160
- * Koichi Sasada (@ko1) and Kenta Murata (@mrkn) for their support and mentorship throughout this project.
204
+ * Koichi Sasada (@ko1), Kenta Murata (@mrkn) and Naotoshi Seo (@sonots) for their support and mentorship throughout this project.
161
205
  * Fukuoka Ruby Award 2017.
206
+ * Tokyo Institute of Technology.
@@ -2,59 +2,63 @@
2
2
 
3
3
  Rubex is a language designed to keep you happy even when writing C extension.
4
4
 
5
- # Table of Contents
6
- <!-- MarkdownTOC autolink="true" bracket="round" depth="3"-->
5
+ <!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-generate-toc again -->
6
+ **Table of Contents**
7
7
 
8
+ - [Rubex (RUBy EXtension Language)](#rubex-ruby-extension-language)
9
+ - [Table of Contents](#table-of-contents)
8
10
  - [Comments](#comments)
9
11
  - [C data types](#c-data-types)
10
- - [Primitive data types](#primitive-data-types)
11
- - [C struct, union and enum](#c-struct-union-and-enum)
12
- - [Forward declarations](#forward-declarations)
13
- - [Pointers](#pointers)
12
+ - [Primitive data types](#primitive-data-types)
13
+ - [C struct, union and enum](#c-struct-union-and-enum)
14
+ - [Forward declarations](#forward-declarations)
15
+ - [Pointers](#pointers)
14
16
  - [Ruby Objects](#ruby-objects)
15
17
  - [Literals](#literals)
16
- - [Integer](#integer)
17
- - [Float](#float)
18
- - [Character](#character)
19
- - [String](#string)
20
- - [Ruby Literals](#ruby-literals)
21
- - [Ruby Symbol](#ruby-symbol)
22
- - [Ruby Array](#ruby-array)
23
- - [Ruby Hash](#ruby-hash)
18
+ - [Integer](#integer)
19
+ - [Float](#float)
20
+ - [Character](#character)
21
+ - [String](#string)
22
+ - [Ruby Literals](#ruby-literals)
23
+ - [Ruby Symbol](#ruby-symbol)
24
+ - [Ruby Array](#ruby-array)
25
+ - [Ruby Hash](#ruby-hash)
24
26
  - [C Functions and Ruby Methods](#c-functions-and-ruby-methods)
25
27
  - [Ruby Constants](#ruby-constants)
26
28
  - [The print statement](#the-print-statement)
27
29
  - [Loops](#loops)
28
- - [The while loop](#the-while-loop)
29
- - [The for loop](#the-for-loop)
30
+ - [The while loop](#the-while-loop)
31
+ - [The for loop](#the-for-loop)
30
32
  - [Conditionals](#conditionals)
31
- - [Important Note](#important-note)
33
+ - [Important Note](#important-note)
32
34
  - [Interfacing C libraries with lib](#interfacing-c-libraries-with-lib)
33
- - [Basic Usage](#basic-usage)
34
- - [Supported declarations](#supported-declarations)
35
- - [Functions](#functions)
36
- - [Variables](#variables)
37
- - [Macros](#macros)
38
- - [Types](#types)
39
- - [Typedefs](#typedefs)
40
- - [Linking Libraries](#linking-libraries)
41
- - [Ready-to-use C functions](#ready-to-use-c-functions)
42
- - [Filename: "rubex/ruby"](#filename-rubexruby)
43
- - [Filename: "rubex/ruby/encoding"](#filename-rubexrubyencoding)
44
- - [Filename: "rubex/stdlib"](#filename-rubexstdlib)
35
+ - [Basic Usage](#basic-usage)
36
+ - [Supported declarations](#supported-declarations)
37
+ - [Functions](#functions)
38
+ - [Variables](#variables)
39
+ - [Macros](#macros)
40
+ - [Types](#types)
41
+ - [Typedefs](#typedefs)
42
+ - [Linking Libraries](#linking-libraries)
43
+ - [Ready-to-use C functions](#ready-to-use-c-functions)
44
+ - [Filename: "rubex/ruby"](#filename-rubexruby)
45
+ - [Filename: "rubex/ruby/encoding"](#filename-rubexrubyencoding)
46
+ - [Filename: "rubex/stdlib"](#filename-rubexstdlib)
45
47
  - [Exception Handling](#exception-handling)
46
48
  - ['Attach' Classes](#attach-classes)
47
- - [The attach keyword](#the-attach-keyword)
48
- - [The data$ variable](#the-data-variable)
49
- - [Special C functions in attach classes](#special-c-functions-in-attach-classes)
50
- - [deallocate](#deallocate)
51
- - [allocate](#allocate)
52
- - [memcount](#memcount)
53
- - [get_struct](#getstruct)
54
- - [gc_mark](#gcmark)
49
+ - [The attach keyword](#the-attach-keyword)
50
+ - [The data$ variable](#the-data-variable)
51
+ - [Special C functions in attach classes](#special-c-functions-in-attach-classes)
52
+ - [deallocate](#deallocate)
53
+ - [allocate](#allocate)
54
+ - [memcount](#memcount)
55
+ - [get_struct](#getstruct)
56
+ - [gc_mark](#gcmark)
55
57
  - [Typecast](#typecast)
56
58
  - [Alias](#alias)
57
59
  - [Conversions between Ruby and C data](#conversions-between-ruby-and-c-data)
60
+ - [Releasing the Global Interpreter Lock](#releasing-the-global-interpreter-lock)
61
+ - [Multi-file rubex programs](#multi-file-rubex-programs)
58
62
  - [C callbacks](#c-callbacks)
59
63
  - [Inline C](#inline-c)
60
64
  - [Handling Strings](#handling-strings)
@@ -62,7 +66,7 @@ Rubex is a language designed to keep you happy even when writing C extension.
62
66
  - [Differences from Ruby](#differences-from-ruby)
63
67
  - [Limitations](#limitations)
64
68
 
65
- <!-- /MarkdownTOC -->
69
+ <!-- markdown-toc end -->
66
70
 
67
71
  # Comments
68
72
 
@@ -640,6 +644,25 @@ The `xfree` function, which is the standard memory freeing function provided by
640
644
 
641
645
  ### allocate
642
646
 
647
+ The `allocate` function is called by the Ruby interpreter before it initializes the class
648
+ using `initialize`. It is here that the C level memory allocations that are assigned to a
649
+ particular class via attached structs should be `xmalloc`'d. The correponding data should be
650
+ freed using `xfree` inside the `deallocate` function that is documented below.
651
+
652
+ Keep in mind that if you choose to define your own `allocate` function, it must have a return
653
+ type `object`. An example `deallocate` would look like so:
654
+ ``` ruby
655
+ struct test
656
+ int *a
657
+ end
658
+
659
+ class A attach test
660
+ cfunc object allocate
661
+ data$.test.a = <int*>xmalloc(sizeof(int)*100)
662
+ end
663
+ end
664
+ ```
665
+
643
666
  ### memcount
644
667
 
645
668
  ### get_struct
@@ -681,7 +704,43 @@ end
681
704
 
682
705
  # Conversions between Ruby and C data
683
706
 
684
- Rubex will implicitly convert most primitive C types like `char`, `int` and `float` to their equivalent Ruby types and vice versa. However, types conversions for user defined types like structs and unions are not supported.
707
+ Rubex will implicitly convert most primitive C types like `char`, `int` and `float`
708
+ to their equivalent Ruby types and vice versa. However, types conversions for user
709
+ defined types like structs and unions are not supported.
710
+
711
+ # Releasing the Global Interpreter Lock
712
+
713
+ Rubex can release the GIL a very simple `no_gil` construct. Some care must be taken when
714
+ using other functions inside this block. As a rule you cannot use any Ruby objects
715
+ inside a `no_gil` block. All data handling must be done _only_ by C data types.
716
+
717
+ Functions that are called inside the `no_gil` block cannot use any Ruby objects either, and
718
+ must be tagged using the `no_gil` keyword. This will ensure that Rubex checks for Ruby
719
+ objects inside these functions and raises an error if you accidentally use Ruby objects. Note
720
+ that these checks are not exhaustive and the user should be careful.
721
+
722
+ Here's an example of using a `no_gil` block from a Ruby method:
723
+ ``` ruby
724
+ cfunc void _work_without_gil(double n) no_gil
725
+ while n > 0 do
726
+ n ** 0.5 + 4
727
+ n -= 1
728
+ end
729
+ end
730
+
731
+ def work_without_gil(n)
732
+ double i = n
733
+ no_gil
734
+ _work_without_gil(i)
735
+ end
736
+
737
+ return i
738
+ end
739
+ ```
740
+
741
+ # Multi-file rubex programs
742
+
743
+
685
744
 
686
745
  # C callbacks
687
746
 
@@ -729,14 +788,23 @@ end
729
788
 
730
789
  # Handling Strings
731
790
 
732
- For purposes of optimization and compatibility with C, Rubex makes certain assumptions about strings. When you assign a Ruby object to a `char*`, Rubex will automatically pass a pointer to the C string contained inside the object to the `char*`, thereby increasing the efficiency of operations on the string. The resulting string is a regular `\0` delimited C string.
791
+ For purposes of optimization and compatibility with C, Rubex makes certain
792
+ assumptions about strings. When you assign a Ruby object to a `char*`, Rubex
793
+ will automatically pass a pointer to the C string contained inside the object
794
+ to the `char*`, thereby increasing the efficiency of operations on the string.
795
+ The resulting string is a regular `\0` delimited C string.
733
796
 
734
- It should be noted that strings MUST use the double quotation syntax (`""`) and not single quotes in all cases. Single quote is reserved for use by C `char` data. For example, to assign a literal value to a C char, you can write `char a = 'b'`, to assign a literal C string to a `char*` array, use `char* a = "hello"`.
797
+ It should be noted that strings MUST use the double quotation syntax (`""`) and
798
+ not single quotes in all cases. Single quote is reserved for use by C `char` data.
799
+ For example, to assign a literal value to a C char, you can write `char a = 'b'`,
800
+ to assign a literal C string to a `char*` array, use `char* a = "hello"`.
735
801
 
736
802
  # Differences from C
737
803
 
738
- * Rubex does not have dereferencing operator (`*`). Instead use `[0]` to access values pointed to by pointers.
739
- * There is no `->` operator for accessing struct elements from a pointer to a struct. Use the `.` operator directly.
804
+ * Rubex does not have dereferencing operator (`*`). Instead use `[0]` to access
805
+ values pointed to by pointers.
806
+ * There is no `->` operator for accessing struct elements from a pointer to a struct.
807
+ Use the `.` operator directly.
740
808
 
741
809
  # Differences from Ruby
742
810
 
@@ -750,4 +818,4 @@ It should be noted that strings MUST use the double quotation syntax (`""`) and
750
818
  Most of the below limitations are temporary and will be taken care of in future versions:
751
819
 
752
820
  * The `require` statement is currently not supported.
753
- * Multi-file Rubex programs are not yet possible.
821
+ * Multi-file Rubex programs are not yet possible.