rubex 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/CONTRIBUTING.md +73 -9
- data/HISTORY.md +19 -0
- data/README.md +53 -8
- data/REFERENCE.md +112 -44
- data/benchmarks/no_gil/no_gil.rb +24 -0
- data/benchmarks/no_gil/no_gil.rubex +22 -0
- data/bin/rubex +1 -1
- data/examples/c_struct_interface/c_struct_interface.rubex +1 -0
- data/lib/rubex.rb +1 -0
- data/lib/rubex/ast.rb +11 -7
- data/lib/rubex/ast/expression.rb +1 -1
- data/lib/rubex/ast/expression/actual_arg_list.rb +7 -0
- data/lib/rubex/ast/expression/analysed_element_ref/c_var_element_ref.rb +5 -2
- data/lib/rubex/ast/expression/analysed_element_ref/ruby_object_element_ref.rb +26 -9
- data/lib/rubex/ast/expression/binary/binary_boolean.rb +1 -1
- data/lib/rubex/ast/expression/binary/binary_expo.rb +34 -0
- data/lib/rubex/ast/expression/binary/colon2.rb +34 -0
- data/lib/rubex/ast/expression/binary/empty_classes.rb +0 -3
- data/lib/rubex/ast/expression/command_call.rb +24 -0
- data/lib/rubex/ast/{statement → expression/command_call}/print.rb +4 -5
- data/lib/rubex/ast/{statement → expression/command_call}/raise.rb +29 -24
- data/lib/rubex/ast/expression/command_call/require.rb +27 -0
- data/lib/rubex/ast/expression/command_call/yield.rb +36 -0
- data/lib/rubex/ast/expression/element_ref.rb +10 -5
- data/lib/rubex/ast/expression/instance_var.rb +33 -0
- data/lib/rubex/ast/expression/method_call.rb +4 -2
- data/lib/rubex/ast/expression/method_call/c_function_call.rb +4 -3
- data/lib/rubex/ast/expression/method_call/ruby_method_call.rb +7 -5
- data/lib/rubex/ast/expression/name.rb +10 -1
- data/lib/rubex/ast/expression/ruby_object_element_ref/ruby_array_element_ref.rb +5 -2
- data/lib/rubex/ast/expression/ruby_object_element_ref/ruby_hash_element_ref.rb +10 -2
- data/lib/rubex/ast/expression/to_ruby_object.rb +1 -0
- data/lib/rubex/ast/expression/unary.rb +7 -3
- data/lib/rubex/ast/expression/unary_base/ampersand.rb +5 -0
- data/lib/rubex/ast/node.rb +213 -185
- data/lib/rubex/ast/node/file_node.rb +25 -0
- data/lib/rubex/ast/node/main_node.rb +56 -0
- data/lib/rubex/ast/statement/begin_block/begin.rb +4 -3
- data/lib/rubex/ast/statement/c_array_decl.rb +1 -1
- data/lib/rubex/ast/statement/c_ptr_decl.rb +2 -0
- data/lib/rubex/ast/statement/no_gil_block.rb +70 -0
- data/lib/rubex/ast/statement/return.rb +1 -0
- data/lib/rubex/ast/top_statement.rb +1 -1
- data/lib/rubex/ast/top_statement/klass.rb +4 -0
- data/lib/rubex/ast/top_statement/klass/attached_klass.rb +88 -10
- data/lib/rubex/ast/top_statement/method_def.rb +2 -3
- data/lib/rubex/ast/top_statement/method_def/c_function_def.rb +10 -4
- data/lib/rubex/cli.rb +11 -6
- data/lib/rubex/code_supervisor.rb +49 -0
- data/lib/rubex/code_writer.rb +22 -1
- data/lib/rubex/compiler.rb +109 -30
- data/lib/rubex/compiler_config.rb +14 -1
- data/lib/rubex/constants.rb +3 -0
- data/lib/rubex/data_type.rb +2 -3
- data/lib/rubex/data_type/ruby_object/ruby_symbol.rb +0 -1
- data/lib/rubex/error.rb +4 -0
- data/lib/rubex/helpers/writers.rb +33 -4
- data/lib/rubex/lexer.rex +9 -1
- data/lib/rubex/lexer.rex.rb +15 -2
- data/lib/rubex/parser.racc +125 -49
- data/lib/rubex/parser.racc.rb +1526 -1376
- data/lib/rubex/rake_task.rb +42 -6
- data/lib/rubex/symbol_table/entry.rb +6 -0
- data/lib/rubex/symbol_table/scope.rb +28 -3
- data/lib/rubex/version.rb +1 -1
- data/rubex.gemspec +1 -0
- data/spec/basic_ruby_method_spec.rb +2 -2
- data/spec/blocks_spec.rb +2 -2
- data/spec/box_op_multi_args_spec.rb +34 -0
- data/spec/c_function_ptrs_spec.rb +2 -2
- data/spec/c_functions_spec.rb +2 -0
- data/spec/c_struct_interface_spec.rb +8 -3
- data/spec/default_args_spec.rb +2 -2
- data/spec/external_c_struct_spec.rb +33 -0
- data/spec/fixtures/api/consumer.rubex +0 -0
- data/spec/fixtures/api/implementation.rubex +0 -0
- data/spec/fixtures/api/implementation.rubexd +0 -0
- data/spec/fixtures/box_op_multi_args/box_op_multi_args.rubex +3 -0
- data/spec/fixtures/c_functions/c_functions.rubex +13 -0
- data/spec/fixtures/c_struct_interface/c_struct_interface.rubex +28 -0
- data/spec/fixtures/class_methods/class_methods.rubex +1 -1
- data/spec/fixtures/error_handling/error_handling.rubex +2 -2
- data/spec/fixtures/external_c_struct/external_c_struct.rubex +16 -0
- data/spec/fixtures/if_else/if_else.rubex +1 -1
- data/spec/fixtures/init_ruby_objects_with_literal_syntax/init_ruby_objects_with_literal_syntax.rubex +1 -1
- data/spec/fixtures/instance_variables/instance_variables.rubex +25 -0
- data/spec/fixtures/loops/loops.rubex +2 -2
- data/spec/fixtures/module/module.rubex +28 -0
- data/spec/fixtures/multi_file_programs/Rakefile +8 -0
- data/spec/fixtures/multi_file_programs/a.rubex +5 -0
- data/spec/fixtures/multi_file_programs/b.rubex +5 -0
- data/spec/fixtures/multi_file_programs/multi_file_programs.rubex +14 -0
- data/spec/fixtures/no_gil/no_gil.rubex +24 -0
- data/spec/fixtures/no_gil_attach_class/no_gil_attach_class.rubex +23 -0
- data/spec/fixtures/no_gil_compile_check/no_gil_compile_check.rubex +4 -0
- data/spec/fixtures/outside_stmts/outside_stmts.rubex +6 -0
- data/spec/fixtures/pow/pow.rubex +4 -0
- data/spec/fixtures/rake_task/single_file/test.rubex +3 -0
- data/spec/fixtures/recursion/recursion.rubex +1 -1
- data/spec/fixtures/ruby_constant_scoping/ruby_constant_scoping.rubex +7 -0
- data/spec/fixtures/ruby_operators/ruby_operators.rubex +1 -1
- data/spec/fixtures/ruby_raise/ruby_raise.rubex +2 -2
- data/spec/fixtures/ruby_types/ruby_types.rubex +4 -4
- data/spec/fixtures/statement_expression/statement_expression.rubex +2 -2
- data/spec/fixtures/static_array/static_array.rubex +3 -3
- data/spec/fixtures/string_literals/string_literals.rubex +12 -2
- data/spec/fixtures/struct/struct.rubex +1 -1
- data/spec/fixtures/var_declarations/var_declarations.rubex +1 -1
- data/spec/implicit_lib_include_spec.rb +2 -2
- data/spec/init_ruby_objects_with_literal_syntax_spec.rb +2 -2
- data/spec/instance_variables_spec.rb +33 -0
- data/spec/loops_spec.rb +2 -2
- data/spec/module_spec.rb +39 -0
- data/spec/multi_file_programs_spec.rb +41 -0
- data/spec/no_gil_attach_class_spec.rb +33 -0
- data/spec/no_gil_compile_check_spec.rb +25 -0
- data/spec/no_gil_spec.rb +36 -0
- data/spec/outside_stmts_spec.rb +34 -0
- data/spec/pow_spec.rb +33 -0
- data/spec/rake_task_spec.rb +142 -0
- data/spec/recursion_spec.rb +4 -4
- data/spec/ruby_constant_scoping_spec.rb +42 -0
- data/spec/ruby_raise_spec.rb +2 -2
- data/spec/ruby_symbols_spec.rb +2 -2
- data/spec/ruby_types_spec.rb +2 -2
- data/spec/spec_helper.rb +17 -3
- data/spec/string_literals_spec.rb +1 -0
- metadata +90 -6
- data/lib/rubex/ast/statement/yield.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c8859787757dadc4f2cadd8cbb2d227d26ae5f69
|
4
|
+
data.tar.gz: bb028214cc70f7fee50d0fd0c185bd89244eb593
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71322d0c3be4a0acedfa74d11789941c43f5cd81613bd771445f6124e48fa84b22bbdb451de731bdc15df1a534715e1628debdc10334cb468773c584bb992746
|
7
|
+
data.tar.gz: 1ec819863e026a14283dfb0d0ffde57df6d29457cb72561f816cc6aa840d29fe01947a1e705550205b5dff30806f1c12873653917ffa1780a9425408dd772d58
|
data/.gitignore
CHANGED
data/CONTRIBUTING.md
CHANGED
@@ -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
|
-
-
|
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
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
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
|
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
|
-
|
121
|
+
Requires Ruby version >= 2.3.0
|
122
122
|
|
123
|
-
|
123
|
+
Install with:
|
124
124
|
```
|
125
|
-
|
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
|
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)
|
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.
|
data/REFERENCE.md
CHANGED
@@ -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
|
-
|
6
|
-
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
-
|
29
|
-
|
30
|
+
- [The while loop](#the-while-loop)
|
31
|
+
- [The for loop](#the-for-loop)
|
30
32
|
- [Conditionals](#conditionals)
|
31
|
-
|
33
|
+
- [Important Note](#important-note)
|
32
34
|
- [Interfacing C libraries with lib](#interfacing-c-libraries-with-lib)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
-
<!--
|
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`
|
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
|
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
|
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
|
739
|
-
|
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.
|