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
@@ -0,0 +1,25 @@
|
|
1
|
+
module Rubex
|
2
|
+
module AST
|
3
|
+
module Node
|
4
|
+
# Class for denoting a rubex file that is required from another rubex file.
|
5
|
+
# Takes the Object scope from the MainNode or other FileNode objects and
|
6
|
+
# uses that for storing any symbols that it encounters.
|
7
|
+
class FileNode < Base
|
8
|
+
def analyse_statement(_local_scope)
|
9
|
+
add_top_statements_to_object_scope
|
10
|
+
super()
|
11
|
+
rescan_declarations @scope
|
12
|
+
end
|
13
|
+
|
14
|
+
def generate_code(supervisor)
|
15
|
+
supervisor.init_file(@file_name)
|
16
|
+
code_writer = supervisor.code(@file_name)
|
17
|
+
code_writer.write_include @file_name
|
18
|
+
generate_header_file @file_name, supervisor.header(@file_name)
|
19
|
+
super
|
20
|
+
generate_init_method code_writer
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Rubex
|
2
|
+
module AST
|
3
|
+
module Node
|
4
|
+
# Main class that acts as the apex node of the Rubex AST.
|
5
|
+
class MainNode < Base
|
6
|
+
|
7
|
+
# Central method that starts that processing of the AST. Called by Compiler.
|
8
|
+
#
|
9
|
+
# @param target_name [String] Target file name of the extension. The Init_
|
10
|
+
# method is named after this.
|
11
|
+
# @param supervisor [Rubex::CodeSupervisor] Object for holding output code
|
12
|
+
# for header and implementation code of each rubex file.
|
13
|
+
def process_statements(target_name, supervisor)
|
14
|
+
if target_name != @file_name
|
15
|
+
raise Rubex::TargetFileMismatchError,
|
16
|
+
"target_name #{target_name} does not match @file_name #{@file_name}"
|
17
|
+
end
|
18
|
+
@scope = Rubex::SymbolTable::Scope::Klass.new('Object', nil)
|
19
|
+
add_top_statements_to_object_scope
|
20
|
+
create_symtab_entries_for_top_statements(@scope)
|
21
|
+
analyse_statement
|
22
|
+
rescan_declarations @scope
|
23
|
+
generate_common_utils_files supervisor
|
24
|
+
generate_header_and_implementation supervisor
|
25
|
+
end
|
26
|
+
|
27
|
+
def generate_common_utils_files supervisor
|
28
|
+
supervisor.init_file(Rubex::COMMON_UTILS_FILE)
|
29
|
+
header = supervisor.header(Rubex::COMMON_UTILS_FILE)
|
30
|
+
header.in_header_guard(Rubex::COMMON_UTILS_CONST) do
|
31
|
+
header << "#include <ruby.h>\n"
|
32
|
+
header << "#include <stdint.h>\n"
|
33
|
+
header << "#include <stdbool.h>\n"
|
34
|
+
header << "#include <math.h>\n"
|
35
|
+
write_usability_functions_header header
|
36
|
+
write_usability_macros header
|
37
|
+
end
|
38
|
+
|
39
|
+
code = supervisor.code(Rubex::COMMON_UTILS_FILE)
|
40
|
+
code.write_include(Rubex::COMMON_UTILS_FILE)
|
41
|
+
write_usability_functions_code code
|
42
|
+
|
43
|
+
Rubex::Compiler::CONFIG.add_dep(Rubex::COMMON_UTILS_FILE)
|
44
|
+
end
|
45
|
+
|
46
|
+
def generate_header_and_implementation(supervisor)
|
47
|
+
generate_header_file @file_name, supervisor.header(@file_name)
|
48
|
+
code_writer = supervisor.code(@file_name)
|
49
|
+
code_writer.write_include @file_name
|
50
|
+
generate_code supervisor
|
51
|
+
generate_init_method code_writer
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -160,16 +160,17 @@ module Rubex
|
|
160
160
|
'begin_block_' + local_scope.klass_name + '_' + local_scope.name + '_' +
|
161
161
|
local_scope.begin_block_counter.to_s
|
162
162
|
end
|
163
|
-
|
163
|
+
|
164
164
|
def create_c_function_to_house_statements(scope)
|
165
165
|
func_name = @block_scope.name
|
166
166
|
arg_list = Statement::ArgumentList.new([
|
167
167
|
AST::Expression::ArgDeclaration.new(
|
168
|
-
|
168
|
+
{ dtype: 'object',
|
169
|
+
variables: [{ ident: 'dummy' }] }
|
169
170
|
)
|
170
171
|
])
|
171
172
|
@begin_func = TopStatement::CFunctionDef.new(
|
172
|
-
'object', '', func_name, arg_list, @statements
|
173
|
+
'object', '', func_name, arg_list, nil, @statements
|
173
174
|
)
|
174
175
|
arg_list.analyse_statement @block_scope
|
175
176
|
add_to_symbol_table @begin_func.name, arg_list, scope
|
@@ -17,7 +17,9 @@ module Rubex
|
|
17
17
|
@type = Helpers.determine_dtype @type, @ptr_level
|
18
18
|
if @value
|
19
19
|
@value.analyse_for_target_type(@type, local_scope)
|
20
|
+
@value.allocate_temps(local_scope)
|
20
21
|
@value = Helpers.to_lhs_type(self, @value)
|
22
|
+
@value.release_temps(local_scope)
|
21
23
|
end
|
22
24
|
|
23
25
|
@entry = local_scope.declare_var name: @name, c_name: @c_name,
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Rubex
|
2
|
+
module AST
|
3
|
+
module Statement
|
4
|
+
class NoGilBlock < Base
|
5
|
+
def initialize statements
|
6
|
+
@statements = statements
|
7
|
+
end
|
8
|
+
|
9
|
+
def analyse_statement(local_scope)
|
10
|
+
local_scope.found_no_gil_block
|
11
|
+
@block_scope = Rubex::SymbolTable::Scope::NoGilBlock.new(
|
12
|
+
block_name(local_scope), local_scope)
|
13
|
+
create_c_function_to_house_statements local_scope.outer_scope
|
14
|
+
# TODO: check if ruby objects exist in the block. Raise error if yes.
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate_code(code, local_scope)
|
18
|
+
code.nl
|
19
|
+
code << "/* no_gil block: */"
|
20
|
+
code.nl
|
21
|
+
super
|
22
|
+
cb_c_name = local_scope.find(@no_gil_func.name).c_name
|
23
|
+
code << "rb_thread_call_without_gvl(#{cb_c_name}, NULL, RUBY_UBF_PROCESS, NULL);"
|
24
|
+
code.nl
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def block_name(local_scope)
|
30
|
+
"no_gil_block_" + local_scope.klass_name + "_" + local_scope.name + "_" +
|
31
|
+
local_scope.no_gil_block_counter.to_s
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_c_function_to_house_statements(outer_scope)
|
35
|
+
func_name = @block_scope.name
|
36
|
+
arg_list = Statement::ArgumentList.new([
|
37
|
+
AST::Expression::ArgDeclaration.new(
|
38
|
+
{
|
39
|
+
dtype: 'void',
|
40
|
+
variables:
|
41
|
+
[{
|
42
|
+
ptr_level: "*",
|
43
|
+
ident: 'dummy'
|
44
|
+
}]
|
45
|
+
})
|
46
|
+
])
|
47
|
+
@no_gil_func = TopStatement::CFunctionDef.new(
|
48
|
+
'void', '*', func_name, arg_list, nil, @statements)
|
49
|
+
arg_list.analyse_statement @block_scope
|
50
|
+
add_to_symbol_table @no_gil_func.name, arg_list, outer_scope
|
51
|
+
@no_gil_func.analyse_statement @block_scope
|
52
|
+
@block_scope.upgrade_symbols_to_global
|
53
|
+
outer_scope.add_no_gil_block_callback @no_gil_func
|
54
|
+
end
|
55
|
+
|
56
|
+
def add_to_symbol_table(func_name, arg_list, outer_scope)
|
57
|
+
c_name = Rubex::C_FUNC_PREFIX + func_name
|
58
|
+
outer_scope.add_c_method(
|
59
|
+
name: func_name,
|
60
|
+
c_name: c_name,
|
61
|
+
extern: false,
|
62
|
+
return_type: DataType::RubyObject.new,
|
63
|
+
arg_list: arg_list,
|
64
|
+
scope: @block_scope
|
65
|
+
)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -1 +1 @@
|
|
1
|
-
Dir[
|
1
|
+
Dir[File.join(File.dirname(File.dirname(__FILE__)), "ast", "top_statement", "**", "*.rb" )].sort.each { |f| require f }
|
@@ -17,13 +17,13 @@ module Rubex
|
|
17
17
|
|
18
18
|
def analyse_statement(outer_scope)
|
19
19
|
super(outer_scope, attach_klass: true)
|
20
|
-
prepare_data_holding_struct
|
20
|
+
prepare_data_holding_struct!
|
21
21
|
prepare_rb_data_type_t_struct
|
22
22
|
detach_and_modify_auxillary_c_functions_from_statements
|
23
23
|
add_auxillary_functions_to_klass_scope
|
24
24
|
prepare_auxillary_c_functions
|
25
25
|
@statements[1..-1].each do |stmt| # 0th stmt is the data struct
|
26
|
-
if
|
26
|
+
if ruby_method_or_c_func_without_gil_lock?(stmt)
|
27
27
|
rewrite_method_with_data_fetching stmt
|
28
28
|
end
|
29
29
|
stmt.analyse_statement @scope
|
@@ -72,6 +72,7 @@ module Rubex
|
|
72
72
|
if stmt.name == ALLOC_FUNC_NAME
|
73
73
|
@auxillary_c_functions[ALLOC_FUNC_NAME] = stmt
|
74
74
|
@user_defined_alloc = true
|
75
|
+
modify_alloc_func stmt
|
75
76
|
indexes << idx
|
76
77
|
elsif stmt.name == DEALLOC_FUNC_NAME
|
77
78
|
@auxillary_c_functions[DEALLOC_FUNC_NAME] = stmt
|
@@ -90,8 +91,8 @@ module Rubex
|
|
90
91
|
end
|
91
92
|
end
|
92
93
|
|
93
|
-
|
94
|
-
|
94
|
+
@statements.delete_if.with_index do |s, i|
|
95
|
+
indexes.include? i
|
95
96
|
end
|
96
97
|
end
|
97
98
|
|
@@ -100,10 +101,22 @@ module Rubex
|
|
100
101
|
write_memcount_c_function code
|
101
102
|
end
|
102
103
|
|
104
|
+
# FIXME : change this. its too ugly.
|
105
|
+
def ugly_code_mod_hack code
|
106
|
+
ret = ""
|
107
|
+
ret << 'return TypedData_Wrap_Struct('
|
108
|
+
ret << "#{@alloc_c_func.type.arg_list[0].entry.c_name},"
|
109
|
+
ret << "&#{@data_type_t}, #{Rubex::POINTER_PREFIX}data);\n"
|
110
|
+
|
111
|
+
c = code.instance_variable_get(:@code)
|
112
|
+
c.insert -4, ret
|
113
|
+
end
|
114
|
+
|
103
115
|
# Actually write the alloc function into C code.
|
104
|
-
def write_alloc_c_function(code)
|
116
|
+
def write_alloc_c_function(code)
|
105
117
|
if user_defined_alloc?
|
106
118
|
@auxillary_c_functions[ALLOC_FUNC_NAME].generate_code code
|
119
|
+
ugly_code_mod_hack code
|
107
120
|
else
|
108
121
|
code.write_c_method_header(
|
109
122
|
type: @alloc_c_func.type.type.to_s,
|
@@ -122,7 +135,7 @@ module Rubex
|
|
122
135
|
lines << 'return TypedData_Wrap_Struct('
|
123
136
|
lines << "#{@alloc_c_func.type.arg_list[0].entry.c_name},"
|
124
137
|
lines << "&#{@data_type_t}, data);\n"
|
125
|
-
|
138
|
+
|
126
139
|
code << lines
|
127
140
|
end
|
128
141
|
end
|
@@ -131,7 +144,7 @@ module Rubex
|
|
131
144
|
# TODO: modify for supporting inheritance
|
132
145
|
def member_struct_allocations
|
133
146
|
c_name = @scope.find(@attached_type).c_name
|
134
|
-
|
147
|
+
"data->#{Rubex::POINTER_PREFIX + @attached_type} = (#{c_name}*)xmalloc(sizeof(#{c_name}));\n"
|
135
148
|
end
|
136
149
|
|
137
150
|
# Actually write the dealloc function into C code.
|
@@ -198,7 +211,7 @@ module Rubex
|
|
198
211
|
|
199
212
|
# Prepare the data holding struct 'data' that will hold a pointer to the
|
200
213
|
# struct that is attached to this class.
|
201
|
-
def prepare_data_holding_struct
|
214
|
+
def prepare_data_holding_struct!
|
202
215
|
struct_name = @name + '_data_struct'
|
203
216
|
declarations = declarations_for_data_struct
|
204
217
|
@data_struct = Statement::CStructOrUnionDef.new(
|
@@ -230,8 +243,8 @@ module Rubex
|
|
230
243
|
prepare_get_struct_c_function
|
231
244
|
end
|
232
245
|
|
233
|
-
def
|
234
|
-
stmt.is_a?(RubyMethodDef) || stmt.is_a?(CFunctionDef)
|
246
|
+
def ruby_method_or_c_func_without_gil_lock?(stmt)
|
247
|
+
stmt.is_a?(RubyMethodDef) || (stmt.is_a?(CFunctionDef) && !stmt.no_gil)
|
235
248
|
end
|
236
249
|
|
237
250
|
# Rewrite method `stmt` so that the `data` variable becomes available
|
@@ -368,6 +381,71 @@ module Rubex
|
|
368
381
|
end
|
369
382
|
end
|
370
383
|
|
384
|
+
# In case of user supplied allocate function, add a statement at the
|
385
|
+
# beginning to declare and obtain the data variable and also add a
|
386
|
+
# return statement involving TypedDataStruct at the end so that the
|
387
|
+
# user is freed from needing to write these.
|
388
|
+
def modify_alloc_func(func)
|
389
|
+
stmts = []
|
390
|
+
stmts << data_var_cptr_decl(nil)
|
391
|
+
stmts.concat data_struct_allocations
|
392
|
+
stmts.reverse.each do |s|
|
393
|
+
func.statements.unshift s
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
# declare a pointer to a data struct.
|
398
|
+
def data_var_cptr_decl(value = nil)
|
399
|
+
Statement::CPtrDecl.new(
|
400
|
+
@data_struct.entry.name, 'data', value, '*', @location)
|
401
|
+
end
|
402
|
+
|
403
|
+
def data_struct_allocations
|
404
|
+
stmts = []
|
405
|
+
# assign malloc for top level data struct
|
406
|
+
rhs = Expression::CommandCall.new(
|
407
|
+
nil, 'xmalloc',
|
408
|
+
Expression::ActualArgList.new(
|
409
|
+
[
|
410
|
+
Expression::SizeOf.new(@data_struct.entry.name, '')
|
411
|
+
])
|
412
|
+
)
|
413
|
+
rhs.typecast = Expression::Typecast.new(@data_struct.entry.name, '*')
|
414
|
+
assign_data_struct = Statement::Assign.new(
|
415
|
+
Expression::Name.new('data'), rhs, @location
|
416
|
+
)
|
417
|
+
|
418
|
+
stmts << assign_data_struct
|
419
|
+
stmts << xmalloc_inner_struct_member
|
420
|
+
stmts
|
421
|
+
end
|
422
|
+
|
423
|
+
def xmalloc_inner_struct_member
|
424
|
+
t = @scope.find(@attached_type).name
|
425
|
+
lhs = Expression::CommandCall.new(
|
426
|
+
Expression::ElementRef.new(
|
427
|
+
'data',
|
428
|
+
Expression::ActualArgList.new(
|
429
|
+
[
|
430
|
+
Expression::Literal::Int.new('0')
|
431
|
+
]
|
432
|
+
)
|
433
|
+
),
|
434
|
+
t,
|
435
|
+
nil
|
436
|
+
)
|
437
|
+
rhs = Expression::CommandCall.new(
|
438
|
+
nil, 'xmalloc',
|
439
|
+
Expression::ActualArgList.new(
|
440
|
+
[
|
441
|
+
Expression::SizeOf.new(t, '')
|
442
|
+
]
|
443
|
+
)
|
444
|
+
)
|
445
|
+
rhs.typecast = Expression::Typecast.new(t, '*')
|
446
|
+
Statement::Assign.new(lhs, rhs, @location)
|
447
|
+
end
|
448
|
+
|
371
449
|
# Modify the dealloc function by adding an argument of type void* so
|
372
450
|
# that it is compatible with what Ruby expects. This is done so that
|
373
451
|
# the user is not burdened with additional knowledge of knowing the
|
@@ -6,7 +6,7 @@ module Rubex
|
|
6
6
|
# Ruby name of the method.
|
7
7
|
attr_reader :name
|
8
8
|
# Method arguments. Accessor because arguments need to be modified in
|
9
|
-
#
|
9
|
+
# case of auxillary C functions of attach classes.
|
10
10
|
attr_accessor :arg_list
|
11
11
|
# The statments/expressions contained within the method.
|
12
12
|
attr_reader :statements
|
@@ -53,7 +53,7 @@ module Rubex
|
|
53
53
|
private
|
54
54
|
|
55
55
|
def generate_function_definition(code, c_function:)
|
56
|
-
declare_types code, @scope
|
56
|
+
declare_types code, @scope.type_entries
|
57
57
|
declare_args code unless c_function
|
58
58
|
declare_vars code, @scope
|
59
59
|
declare_carrays code, @scope
|
@@ -104,7 +104,6 @@ module Rubex
|
|
104
104
|
end
|
105
105
|
end
|
106
106
|
end
|
107
|
-
|
108
107
|
end
|
109
108
|
end
|
110
109
|
end
|
@@ -2,25 +2,31 @@ module Rubex
|
|
2
2
|
module AST
|
3
3
|
module TopStatement
|
4
4
|
class CFunctionDef < MethodDef
|
5
|
-
attr_reader :type, :return_ptr_level
|
5
|
+
attr_reader :type, :return_ptr_level, :no_gil
|
6
6
|
|
7
|
-
def initialize(type, return_ptr_level, name, arg_list, statements)
|
7
|
+
def initialize(type, return_ptr_level, name, arg_list, function_tags, statements)
|
8
8
|
super(name, arg_list, statements)
|
9
9
|
@type = type
|
10
10
|
@return_ptr_level = return_ptr_level
|
11
|
+
@function_tags = function_tags
|
12
|
+
@no_gil = false
|
13
|
+
if @function_tags == "no_gil"
|
14
|
+
@no_gil = true
|
15
|
+
end
|
11
16
|
end
|
12
17
|
|
13
18
|
def analyse_statement(outer_scope, extern: false)
|
14
19
|
super(outer_scope)
|
20
|
+
@entry.no_gil = @no_gil
|
15
21
|
end
|
16
22
|
|
17
23
|
def generate_code(code)
|
18
24
|
code.write_c_method_header(type: @entry.type.type.to_s,
|
19
|
-
c_name: @entry.c_name,
|
25
|
+
c_name: @entry.c_name,
|
26
|
+
args: Helpers.create_arg_arrays(@arg_list))
|
20
27
|
super code, c_function: true
|
21
28
|
end
|
22
29
|
end
|
23
|
-
|
24
30
|
end
|
25
31
|
end
|
26
32
|
end
|