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