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.
- 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.
|