rubex 0.1 → 0.1.1
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 +3 -2
- data/.travis.yml +9 -1
- data/CONTRIBUTING.md +2 -2
- data/README.md +4 -1
- data/Rakefile +2 -2
- data/bin/rubex +4 -5
- data/lib/rubex.rb +4 -4
- data/lib/rubex/ast.rb +4 -1
- data/lib/rubex/ast/expression.rb +22 -1191
- data/lib/rubex/ast/expression/actual_arg_list.rb +40 -0
- data/lib/rubex/ast/expression/analysed_element_ref.rb +26 -0
- data/lib/rubex/ast/expression/analysed_element_ref/c_var_element_ref.rb +30 -0
- data/lib/rubex/ast/expression/analysed_element_ref/ruby_object_element_ref.rb +42 -0
- data/lib/rubex/ast/expression/arg_declaration.rb +43 -0
- data/lib/rubex/ast/expression/binary.rb +57 -0
- data/lib/rubex/ast/expression/binary/binary_boolean.rb +23 -0
- data/lib/rubex/ast/expression/binary/binary_boolean_special_op.rb +20 -0
- data/lib/rubex/ast/expression/binary/empty_classes.rb +62 -0
- data/lib/rubex/ast/expression/block_given.rb +15 -0
- data/lib/rubex/ast/expression/coerce_object.rb +15 -0
- data/lib/rubex/ast/expression/command_call.rb +74 -0
- data/lib/rubex/ast/expression/command_call/struct_or_union_member_call.rb +38 -0
- data/lib/rubex/ast/expression/element_ref.rb +64 -0
- data/lib/rubex/ast/expression/empty.rb +13 -0
- data/lib/rubex/ast/expression/from_ruby_object.rb +20 -0
- data/lib/rubex/ast/expression/func_ptr_arg_declaration.rb +21 -0
- data/lib/rubex/ast/expression/func_ptr_internal_arg_declaration.rb +13 -0
- data/lib/rubex/ast/expression/literal.rb +30 -0
- data/lib/rubex/ast/expression/literal/array_lit.rb +51 -0
- data/lib/rubex/ast/expression/literal/c_null.rb +15 -0
- data/lib/rubex/ast/expression/literal/char.rb +36 -0
- data/lib/rubex/ast/expression/literal/double.rb +14 -0
- data/lib/rubex/ast/expression/literal/false.rb +33 -0
- data/lib/rubex/ast/expression/literal/hash_lit.rb +45 -0
- data/lib/rubex/ast/expression/literal/int.rb +14 -0
- data/lib/rubex/ast/expression/literal/nil.rb +14 -0
- data/lib/rubex/ast/expression/literal/ruby_symbol.rb +22 -0
- data/lib/rubex/ast/expression/literal/string_lit.rb +45 -0
- data/lib/rubex/ast/expression/literal/true.rb +29 -0
- data/lib/rubex/ast/expression/method_call.rb +52 -0
- data/lib/rubex/ast/expression/method_call/c_function_call.rb +40 -0
- data/lib/rubex/ast/expression/method_call/ruby_method_call.rb +83 -0
- data/lib/rubex/ast/expression/name.rb +127 -0
- data/lib/rubex/ast/expression/ruby_constant.rb +25 -0
- data/lib/rubex/ast/expression/ruby_object_element_ref/ruby_array_element_ref.rb +20 -0
- data/lib/rubex/ast/expression/ruby_object_element_ref/ruby_hash_element_ref.rb +22 -0
- data/lib/rubex/ast/expression/self.rb +15 -0
- data/lib/rubex/ast/expression/size_of.rb +22 -0
- data/lib/rubex/ast/expression/struct_or_union_member_call/element_ref_member_call.rb +23 -0
- data/lib/rubex/ast/expression/to_ruby_object.rb +21 -0
- data/lib/rubex/ast/expression/typecast.rb +20 -0
- data/lib/rubex/ast/expression/typecast_to.rb +10 -0
- data/lib/rubex/ast/expression/unary.rb +37 -0
- data/lib/rubex/ast/expression/unary_base.rb +24 -0
- data/lib/rubex/ast/expression/unary_base/ampersand.rb +16 -0
- data/lib/rubex/ast/expression/unary_base/unary_bit_not.rb +18 -0
- data/lib/rubex/ast/expression/unary_base/unary_not.rb +18 -0
- data/lib/rubex/ast/expression/unary_base/unary_sub.rb +18 -0
- data/lib/rubex/ast/node.rb +111 -111
- data/lib/rubex/ast/statement.rb +9 -1160
- data/lib/rubex/ast/statement/alias.rb +43 -0
- data/lib/rubex/ast/statement/argument_list.rb +59 -0
- data/lib/rubex/ast/statement/assign.rb +35 -0
- data/lib/rubex/ast/statement/begin_block.rb +14 -0
- data/lib/rubex/ast/statement/begin_block/begin.rb +202 -0
- data/lib/rubex/ast/statement/begin_block/else.rb +21 -0
- data/lib/rubex/ast/statement/begin_block/ensure.rb +21 -0
- data/lib/rubex/ast/statement/begin_block/rescue.rb +34 -0
- data/lib/rubex/ast/statement/break.rb +18 -0
- data/lib/rubex/ast/statement/c_array_decl.rb +49 -0
- data/lib/rubex/ast/statement/c_base_type.rb +26 -0
- data/lib/rubex/ast/statement/c_function_decl.rb +30 -0
- data/lib/rubex/ast/statement/c_ptr_decl.rb +52 -0
- data/lib/rubex/ast/statement/c_ptr_decl/c_ptr_func_decl.rb +25 -0
- data/lib/rubex/ast/statement/c_struct_or_union_def.rb +49 -0
- data/lib/rubex/ast/statement/expression.rb +26 -0
- data/lib/rubex/ast/statement/for.rb +73 -0
- data/lib/rubex/ast/statement/forward_decl.rb +31 -0
- data/lib/rubex/ast/statement/if_block.rb +64 -0
- data/lib/rubex/ast/statement/if_block/else.rb +30 -0
- data/lib/rubex/ast/statement/if_block/elsif.rb +22 -0
- data/lib/rubex/ast/statement/if_block/helper.rb +38 -0
- data/lib/rubex/ast/statement/print.rb +49 -0
- data/lib/rubex/ast/statement/raise.rb +66 -0
- data/lib/rubex/ast/statement/return.rb +45 -0
- data/lib/rubex/ast/statement/var_decl.rb +49 -0
- data/lib/rubex/ast/statement/while.rb +34 -0
- data/lib/rubex/ast/statement/yield.rb +41 -0
- data/lib/rubex/ast/top_statement.rb +1 -815
- data/lib/rubex/ast/top_statement/c_bindings.rb +145 -0
- data/lib/rubex/ast/top_statement/klass.rb +125 -0
- data/lib/rubex/ast/top_statement/klass/attached_klass.rb +417 -0
- data/lib/rubex/ast/top_statement/method_def.rb +110 -0
- data/lib/rubex/ast/top_statement/method_def/c_function_def.rb +26 -0
- data/lib/rubex/ast/top_statement/method_def/ruby_method_def.rb +33 -0
- data/lib/rubex/cli.rb +26 -0
- data/lib/rubex/code_writer.rb +1 -1
- data/lib/rubex/compiler.rb +49 -28
- data/lib/rubex/compiler_config.rb +4 -2
- data/lib/rubex/constants.rb +71 -71
- data/lib/rubex/data_type.rb +9 -675
- data/lib/rubex/data_type/c_array.rb +33 -0
- data/lib/rubex/data_type/c_function.rb +23 -0
- data/lib/rubex/data_type/c_ptr.rb +71 -0
- data/lib/rubex/data_type/c_str.rb +23 -0
- data/lib/rubex/data_type/c_struct_or_union.rb +23 -0
- data/lib/rubex/data_type/char.rb +30 -0
- data/lib/rubex/data_type/f_32.rb +38 -0
- data/lib/rubex/data_type/f_64.rb +38 -0
- data/lib/rubex/data_type/int.rb +32 -0
- data/lib/rubex/data_type/int/c_boolean.rb +13 -0
- data/lib/rubex/data_type/int_16.rb +32 -0
- data/lib/rubex/data_type/int_32.rb +32 -0
- data/lib/rubex/data_type/int_64.rb +36 -0
- data/lib/rubex/data_type/int_8.rb +33 -0
- data/lib/rubex/data_type/l_int.rb +38 -0
- data/lib/rubex/data_type/l_l_int.rb +26 -0
- data/lib/rubex/data_type/ruby_method.rb +22 -0
- data/lib/rubex/data_type/ruby_object.rb +19 -0
- data/lib/rubex/data_type/ruby_object/boolean.rb +11 -0
- data/lib/rubex/data_type/ruby_object/boolean/false_type.rb +5 -0
- data/lib/rubex/data_type/ruby_object/boolean/true_type.rb +5 -0
- data/lib/rubex/data_type/ruby_object/nil_type.rb +9 -0
- data/lib/rubex/data_type/ruby_object/ruby_array.rb +10 -0
- data/lib/rubex/data_type/ruby_object/ruby_constant.rb +18 -0
- data/lib/rubex/data_type/ruby_object/ruby_constant/ruby_class.rb +18 -0
- data/lib/rubex/data_type/ruby_object/ruby_hash.rb +9 -0
- data/lib/rubex/data_type/ruby_object/ruby_string.rb +10 -0
- data/lib/rubex/data_type/ruby_object/ruby_symbol.rb +10 -0
- data/lib/rubex/data_type/type_def.rb +34 -0
- data/lib/rubex/data_type/u_char.rb +27 -0
- data/lib/rubex/data_type/u_int.rb +32 -0
- data/lib/rubex/data_type/u_int_16.rb +22 -0
- data/lib/rubex/data_type/u_int_32.rb +22 -0
- data/lib/rubex/data_type/u_int_64.rb +26 -0
- data/lib/rubex/data_type/u_int_8.rb +22 -0
- data/lib/rubex/data_type/u_l_int.rb +36 -0
- data/lib/rubex/data_type/u_l_int/size_t.rb +10 -0
- data/lib/rubex/data_type/u_l_l_int.rb +26 -0
- data/lib/rubex/data_type/void.rb +15 -0
- data/lib/rubex/data_type_helpers/float_helpers.rb +8 -0
- data/lib/rubex/data_type_helpers/helpers.rb +48 -0
- data/lib/rubex/data_type_helpers/int_helpers.rb +10 -0
- data/lib/rubex/data_type_helpers/u_int_helpers.rb +11 -0
- data/lib/rubex/helpers.rb +35 -118
- data/lib/rubex/helpers/node_type_methods.rb +9 -0
- data/lib/rubex/helpers/writers.rb +79 -0
- data/lib/rubex/parser.racc +83 -34
- data/lib/rubex/parser.racc.rb +233 -184
- data/lib/rubex/version.rb +2 -2
- data/rubex.gemspec +2 -0
- data/spec/basic_ruby_method_spec.rb +1 -1
- data/spec/binding_ptr_args_spec.rb +2 -2
- data/spec/bitwise_operators_spec.rb +1 -1
- data/spec/blocks_spec.rb +2 -2
- data/spec/c_bindings_spec.rb +1 -1
- data/spec/c_constants_spec.rb +1 -1
- data/spec/c_function_ptrs_spec.rb +1 -1
- data/spec/c_functions_spec.rb +2 -2
- data/spec/c_struct_interface_spec.rb +1 -1
- data/spec/call_by_reference_spec.rb +2 -2
- data/spec/class_methods_spec.rb +2 -2
- data/spec/class_spec.rb +4 -4
- data/spec/cli_spec.rb +43 -0
- data/spec/comments_spec.rb +2 -2
- data/spec/default_args_spec.rb +21 -23
- data/spec/error_handling_spec.rb +1 -1
- data/spec/examples_spec.rb +4 -4
- data/spec/expressions_spec.rb +1 -1
- data/spec/fixtures/cli/cli.rubex +3 -0
- data/spec/fixtures/examples/array_to_hash.rubex +1 -1
- data/spec/fixtures/examples/rcsv.rubex +10 -6
- data/spec/fixtures/loops/loops.rubex +1 -1
- data/spec/fixtures/ruby_strings/string_blank_bm.rb +7 -5
- data/spec/fixtures/struct/struct.rubex +7 -2
- data/spec/fixtures/temp_allocation/temp_allocation.rubex +8 -0
- data/spec/if_else_spec.rb +3 -7
- data/spec/implicit_lib_include_spec.rb +1 -1
- data/spec/init_ruby_objects_with_literal_syntax_spec.rb +1 -1
- data/spec/loops_spec.rb +1 -1
- data/spec/recursion_spec.rb +18 -21
- data/spec/ruby_constant_method_calls_spec.rb +4 -4
- data/spec/ruby_operators_spec.rb +1 -1
- data/spec/ruby_raise_spec.rb +1 -1
- data/spec/ruby_strings_spec.rb +3 -3
- data/spec/ruby_symbols_spec.rb +1 -1
- data/spec/ruby_types_spec.rb +2 -2
- data/spec/spec_helper.rb +42 -10
- data/spec/statement_expression_spec.rb +3 -3
- data/spec/static_array_spec.rb +3 -3
- data/spec/string_literals_spec.rb +2 -2
- data/spec/struct_spec.rb +4 -4
- data/spec/temp_allocation_spec.rb +35 -0
- data/spec/typecasting_spec.rb +2 -2
- data/spec/var_declarions_spec.rb +2 -2
- metadata +168 -3
@@ -0,0 +1,22 @@
|
|
1
|
+
module Rubex
|
2
|
+
module AST
|
3
|
+
module Expression
|
4
|
+
# C sizeof operator.
|
5
|
+
class SizeOf < Base
|
6
|
+
def initialize(type, ptr_level)
|
7
|
+
@type, @ptr_level = type, ptr_level
|
8
|
+
end
|
9
|
+
|
10
|
+
def analyse_types(local_scope)
|
11
|
+
@size_of_type = Helpers.determine_dtype @type, @ptr_level
|
12
|
+
@type = DataType::ULInt.new
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def c_code(_local_scope)
|
17
|
+
"sizeof(#{@size_of_type})"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Rubex
|
2
|
+
module AST
|
3
|
+
module Expression
|
4
|
+
class ElementRefMemberCall < StructOrUnionMemberCall
|
5
|
+
def analyse_types(local_scope, struct_scope)
|
6
|
+
@command.analyse_types local_scope, struct_scope
|
7
|
+
@type = @command.type
|
8
|
+
@has_temp = @command.has_temp
|
9
|
+
@subexprs = [@command]
|
10
|
+
end
|
11
|
+
|
12
|
+
def generate_evaluation_code(code, local_scope)
|
13
|
+
@command.generate_element_ref_code @expr, code, local_scope
|
14
|
+
@c_code = @command.c_code(local_scope)
|
15
|
+
end
|
16
|
+
|
17
|
+
def c_code(local_scope)
|
18
|
+
@c_code
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Rubex
|
2
|
+
module AST
|
3
|
+
module Expression
|
4
|
+
# internal node for converting to ruby object.
|
5
|
+
class ToRubyObject < CoerceObject
|
6
|
+
attr_reader :type
|
7
|
+
|
8
|
+
def initialize(expr)
|
9
|
+
@expr = expr
|
10
|
+
@type = Rubex::DataType::RubyObject.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def c_code(local_scope)
|
14
|
+
t = @expr.type
|
15
|
+
t = t.c_function? || t.alias_type? ? t.type : t
|
16
|
+
t.to_ruby_object(@expr.c_code(local_scope)).to_s
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Rubex
|
2
|
+
module AST
|
3
|
+
module Expression
|
4
|
+
class Typecast < Base
|
5
|
+
def initialize(dtype, ptr_level)
|
6
|
+
@dtype = dtype
|
7
|
+
@ptr_level = ptr_level
|
8
|
+
end
|
9
|
+
|
10
|
+
def analyse_types(_local_scope)
|
11
|
+
@type = Rubex::Helpers.determine_dtype @dtype, @ptr_level
|
12
|
+
end
|
13
|
+
|
14
|
+
def c_code(_local_scope)
|
15
|
+
"(#{@type})"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative 'unary_base'
|
2
|
+
Dir['./lib/rubex/ast/expression/unary_base/*.rb'].each { |f| require f }
|
3
|
+
module Rubex
|
4
|
+
module AST
|
5
|
+
module Expression
|
6
|
+
class Unary < Base
|
7
|
+
OP_CLASS_MAP = {
|
8
|
+
'&' => Rubex::AST::Expression::Ampersand,
|
9
|
+
'-' => Rubex::AST::Expression::UnarySub,
|
10
|
+
'!' => Rubex::AST::Expression::UnaryNot,
|
11
|
+
'~' => Rubex::AST::Expression::UnaryBitNot
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
def initialize(operator, expr)
|
15
|
+
@operator = operator
|
16
|
+
@expr = expr
|
17
|
+
end
|
18
|
+
|
19
|
+
def analyse_types(local_scope)
|
20
|
+
@expr = OP_CLASS_MAP[@operator].new(@expr)
|
21
|
+
@expr.analyse_types local_scope
|
22
|
+
@type = @expr.type
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
def generate_evaluation_code(code, local_scope)
|
27
|
+
@expr.generate_evaluation_code code, local_scope
|
28
|
+
end
|
29
|
+
|
30
|
+
def c_code(local_scope)
|
31
|
+
code = super
|
32
|
+
code << @expr.c_code(local_scope)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Rubex
|
2
|
+
module AST
|
3
|
+
module Expression
|
4
|
+
|
5
|
+
class UnaryBase < Base
|
6
|
+
def initialize expr
|
7
|
+
@expr = expr
|
8
|
+
end
|
9
|
+
|
10
|
+
def analyse_types local_scope
|
11
|
+
@expr.analyse_types local_scope
|
12
|
+
@expr = @expr.to_ruby_object if @expr.type.object?
|
13
|
+
@type = @expr.type
|
14
|
+
@expr.allocate_temps local_scope
|
15
|
+
@expr.release_temps local_scope
|
16
|
+
end
|
17
|
+
|
18
|
+
def generate_evaluation_code code, local_scope
|
19
|
+
@expr.generate_evaluation_code code, local_scope
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Rubex
|
2
|
+
module AST
|
3
|
+
module Expression
|
4
|
+
class Ampersand < UnaryBase
|
5
|
+
def analyse_types(local_scope)
|
6
|
+
@expr.analyse_types local_scope
|
7
|
+
@type = DataType::CPtr.new @expr.type
|
8
|
+
end
|
9
|
+
|
10
|
+
def c_code(local_scope)
|
11
|
+
"&#{@expr.c_code(local_scope)}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Rubex
|
2
|
+
module AST
|
3
|
+
module Expression
|
4
|
+
class UnaryBitNot < UnaryBase
|
5
|
+
attr_reader :type
|
6
|
+
|
7
|
+
def c_code(local_scope)
|
8
|
+
code = @expr.c_code(local_scope)
|
9
|
+
if @type.object?
|
10
|
+
"rb_funcall(#{code}, rb_intern(\"~\"), 0)"
|
11
|
+
else
|
12
|
+
"~#{code}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Rubex
|
2
|
+
module AST
|
3
|
+
module Expression
|
4
|
+
class UnaryNot < UnaryBase
|
5
|
+
attr_reader :type
|
6
|
+
|
7
|
+
def c_code(local_scope)
|
8
|
+
code = @expr.c_code(local_scope)
|
9
|
+
if @type.object?
|
10
|
+
"rb_funcall(#{code}, rb_intern(\"!\"), 0)"
|
11
|
+
else
|
12
|
+
"!#{code}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Rubex
|
2
|
+
module AST
|
3
|
+
module Expression
|
4
|
+
class UnarySub < UnaryBase
|
5
|
+
attr_reader :type
|
6
|
+
|
7
|
+
def c_code(local_scope)
|
8
|
+
code = @expr.c_code(local_scope)
|
9
|
+
if @type.object?
|
10
|
+
"rb_funcall(#{code}, rb_intern(\"-\"), 0)"
|
11
|
+
else
|
12
|
+
"-#{code}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/rubex/ast/node.rb
CHANGED
@@ -1,15 +1,16 @@
|
|
1
|
+
require 'rubex/helpers'
|
1
2
|
module Rubex
|
2
3
|
module AST
|
3
4
|
class Node
|
4
5
|
include Rubex::Helpers::Writers
|
5
6
|
attr_reader :statements
|
6
7
|
|
7
|
-
def initialize
|
8
|
+
def initialize(statements)
|
8
9
|
@statements = statements.flatten
|
9
10
|
end
|
10
11
|
|
11
|
-
def process_statements
|
12
|
-
@scope = Rubex::SymbolTable::Scope::Klass.new
|
12
|
+
def process_statements(target_name, code)
|
13
|
+
@scope = Rubex::SymbolTable::Scope::Klass.new('Object', nil)
|
13
14
|
add_top_statements_to_object_scope
|
14
15
|
analyse_statement
|
15
16
|
rescan_declarations @scope
|
@@ -18,11 +19,11 @@ module Rubex
|
|
18
19
|
generate_init_method target_name, code
|
19
20
|
end
|
20
21
|
|
21
|
-
def ==
|
22
|
+
def ==(other)
|
22
23
|
self.class == other.class
|
23
24
|
end
|
24
25
|
|
25
|
-
|
26
|
+
private
|
26
27
|
|
27
28
|
# Scan all the statements that do not belong to any particular class
|
28
29
|
# (meaning that they belong to Object) and add them to the Object class,
|
@@ -32,7 +33,7 @@ module Rubex
|
|
32
33
|
combined_statements = []
|
33
34
|
@statements.each do |stmt|
|
34
35
|
if stmt.is_a?(TopStatement::Klass) || stmt.is_a?(TopStatement::CBindings)
|
35
|
-
|
36
|
+
unless temp.empty?
|
36
37
|
object_klass = TopStatement::Klass.new('Object', @scope, temp)
|
37
38
|
combined_statements << object_klass
|
38
39
|
end
|
@@ -44,23 +45,24 @@ module Rubex
|
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
47
|
-
|
48
|
+
unless temp.empty?
|
48
49
|
combined_statements << TopStatement::Klass.new('Object', @scope, temp)
|
49
50
|
end
|
50
51
|
|
51
52
|
@statements = combined_statements
|
52
53
|
end
|
53
54
|
|
54
|
-
def generate_preamble
|
55
|
+
def generate_preamble(code)
|
55
56
|
code << "#include <ruby.h>\n"
|
56
57
|
code << "#include <stdint.h>\n"
|
57
58
|
code << "#include <stdbool.h>\n"
|
58
59
|
@scope.include_files.each do |name|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
60
|
+
code <<
|
61
|
+
if name[0] == '<' && name[-1] == '>'
|
62
|
+
"#include #{name}\n"
|
63
|
+
else
|
64
|
+
"#include \"#{name}\"\n"
|
65
|
+
end
|
64
66
|
end
|
65
67
|
write_usability_macros code
|
66
68
|
@statements.grep(Rubex::AST::TopStatement::Klass).each do |klass|
|
@@ -73,41 +75,41 @@ module Rubex
|
|
73
75
|
code.nl
|
74
76
|
end
|
75
77
|
|
76
|
-
def write_global_variable_declarations
|
78
|
+
def write_global_variable_declarations(code)
|
77
79
|
@statements.each do |stmt|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end # if
|
88
|
-
end # .each
|
80
|
+
next unless stmt.is_a?(TopStatement::Klass)
|
81
|
+
stmt.statements.each do |s|
|
82
|
+
next unless s.is_a?(TopStatement::MethodDef)
|
83
|
+
s.scope.global_entries.each do |g|
|
84
|
+
code << "static #{g.type} #{g.c_name};"
|
85
|
+
code.nl
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
89
|
end
|
90
90
|
|
91
|
-
def write_user_klasses
|
91
|
+
def write_user_klasses(code)
|
92
92
|
code.nl
|
93
93
|
@scope.ruby_class_entries.each do |klass|
|
94
|
-
|
95
|
-
|
94
|
+
unless Rubex::DEFAULT_CLASS_MAPPINGS.has_key?(klass.name)
|
95
|
+
code << "VALUE #{klass.c_name};"
|
96
|
+
code.nl
|
97
|
+
end
|
96
98
|
end
|
97
99
|
end
|
98
100
|
|
99
|
-
def write_usability_macros
|
101
|
+
def write_usability_macros(code)
|
100
102
|
code.nl
|
101
|
-
code.c_macro Rubex::RUBEX_PREFIX +
|
103
|
+
code.c_macro Rubex::RUBEX_PREFIX + 'INT2BOOL(arg) (arg ? Qtrue : Qfalse)'
|
102
104
|
code.nl
|
103
105
|
end
|
104
106
|
|
105
|
-
def write_usability_functions
|
107
|
+
def write_usability_functions(code)
|
106
108
|
code.nl
|
107
109
|
write_char_2_ruby_str code
|
108
110
|
end
|
109
111
|
|
110
|
-
def write_char_2_ruby_str
|
112
|
+
def write_char_2_ruby_str(code)
|
111
113
|
code << "VALUE #{Rubex::C_FUNC_CHAR2RUBYSTR}(char ch);"
|
112
114
|
code.nl
|
113
115
|
code << "VALUE #{Rubex::C_FUNC_CHAR2RUBYSTR}(char ch)"
|
@@ -116,27 +118,27 @@ module Rubex
|
|
116
118
|
code << "s[0] = ch;\n"
|
117
119
|
code << "s[1] = '\\0';\n"
|
118
120
|
code << "return rb_str_new2(s);\n"
|
119
|
-
end
|
121
|
+
end
|
120
122
|
end
|
121
123
|
|
122
|
-
def write_function_declarations
|
124
|
+
def write_function_declarations(code)
|
123
125
|
@statements.each do |stmt|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
126
|
+
next unless stmt.is_a?(Rubex::AST::TopStatement::Klass)
|
127
|
+
stmt.scope.ruby_method_entries.each do |entry|
|
128
|
+
code.write_ruby_method_header(
|
129
|
+
type: entry.type.type.to_s, c_name: entry.c_name
|
130
|
+
)
|
131
|
+
code.colon
|
132
|
+
end
|
130
133
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
end
|
134
|
+
stmt.scope.c_method_entries.each do |entry|
|
135
|
+
next if entry.extern?
|
136
|
+
code.write_c_method_header(
|
137
|
+
type: entry.type.type.to_s,
|
138
|
+
c_name: entry.c_name,
|
139
|
+
args: Helpers.create_arg_arrays(entry.type.arg_list)
|
140
|
+
)
|
141
|
+
code.colon
|
140
142
|
end
|
141
143
|
end
|
142
144
|
end
|
@@ -150,76 +152,76 @@ module Rubex
|
|
150
152
|
|
151
153
|
def create_symtab_entries_for_top_statements
|
152
154
|
@statements.each do |stat|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
else
|
168
|
-
ancestor_scope = ancestor_entry&.type&.scope || @scope
|
169
|
-
end
|
170
|
-
klass_scope = Rubex::SymbolTable::Scope::Klass.new(
|
171
|
-
name, ancestor_scope)
|
155
|
+
next unless stat.is_a? Rubex::AST::TopStatement::Klass
|
156
|
+
name = stat.name
|
157
|
+
# The top level scope in Ruby is Object. The Object class's immediate
|
158
|
+
# ancestor is also Object. Hence, it is important to set the class
|
159
|
+
# scope and ancestor scope of Object as Object, and make sure that
|
160
|
+
# the same scope object is used for 'Object' class every single time
|
161
|
+
# throughout the compilation process.
|
162
|
+
if name != 'Object'
|
163
|
+
ancestor_entry = @scope.find(stat.ancestor)
|
164
|
+
if !ancestor_entry && Rubex::DEFAULT_CLASS_MAPPINGS[stat.ancestor]
|
165
|
+
ancestor_c_name = Rubex::DEFAULT_CLASS_MAPPINGS[stat.ancestor]
|
166
|
+
ancestor_scope = object_or_stdlib_klass_scope stat.ancestor
|
167
|
+
@scope.add_ruby_class(name: stat.ancestor, c_name: ancestor_c_name,
|
168
|
+
scope: @scope, ancestor: nil, extern: true)
|
172
169
|
else
|
173
|
-
ancestor_scope = @scope
|
174
|
-
klass_scope = @scope
|
170
|
+
ancestor_scope = ancestor_entry&.type&.scope || @scope
|
175
171
|
end
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
172
|
+
klass_scope = Rubex::SymbolTable::Scope::Klass.new(
|
173
|
+
name, ancestor_scope
|
174
|
+
)
|
175
|
+
else
|
176
|
+
ancestor_scope = @scope
|
177
|
+
klass_scope = @scope
|
180
178
|
end
|
179
|
+
c_name = c_name_for_class name
|
180
|
+
|
181
|
+
@scope.add_ruby_class(name: name, c_name: c_name, scope: klass_scope,
|
182
|
+
ancestor: ancestor_scope, extern: false)
|
181
183
|
end
|
182
184
|
end
|
183
185
|
|
184
|
-
def object_or_stdlib_klass_scope
|
185
|
-
name != 'Object' ? Rubex::SymbolTable::Scope::Klass.new(name, nil) :
|
186
|
+
def object_or_stdlib_klass_scope(name)
|
187
|
+
name != 'Object' ? Rubex::SymbolTable::Scope::Klass.new(name, nil) :
|
186
188
|
@scope
|
187
189
|
end
|
188
190
|
|
189
|
-
def c_name_for_class
|
191
|
+
def c_name_for_class(name)
|
190
192
|
c_name =
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
193
|
+
if Rubex::DEFAULT_CLASS_MAPPINGS.key? name
|
194
|
+
Rubex::DEFAULT_CLASS_MAPPINGS[name]
|
195
|
+
else
|
196
|
+
Rubex::RUBY_CLASS_PREFIX + name
|
197
|
+
end
|
196
198
|
|
197
199
|
c_name
|
198
200
|
end
|
199
201
|
|
200
|
-
def rescan_declarations
|
202
|
+
def rescan_declarations(_scope)
|
201
203
|
@statements.each do |stat|
|
202
|
-
stat.respond_to?(:rescan_declarations)
|
204
|
+
stat.respond_to?(:rescan_declarations) &&
|
203
205
|
stat.rescan_declarations(@scope)
|
204
206
|
end
|
205
207
|
end
|
206
208
|
|
207
|
-
def generate_code
|
209
|
+
def generate_code(code)
|
208
210
|
@statements.each do |stat|
|
209
211
|
stat.generate_code code
|
210
212
|
end
|
211
213
|
end
|
212
214
|
|
213
|
-
def generate_init_method
|
215
|
+
def generate_init_method(target_name, code)
|
214
216
|
name = "Init_#{target_name}"
|
215
217
|
code.new_line
|
216
|
-
code.write_func_declaration type:
|
217
|
-
code.write_c_method_header type:
|
218
|
+
code.write_func_declaration type: 'void', c_name: name, args: [], static: false
|
219
|
+
code.write_c_method_header type: 'void', c_name: name, args: [], static: false
|
218
220
|
code.block do
|
219
221
|
@statements.each do |top_stmt|
|
220
222
|
if top_stmt.is_a?(TopStatement::Klass) && top_stmt.name != 'Object'
|
221
223
|
entry = @scope.find top_stmt.name
|
222
|
-
code.declare_variable type:
|
224
|
+
code.declare_variable type: 'VALUE', c_name: entry.c_name
|
223
225
|
end
|
224
226
|
end
|
225
227
|
code.nl
|
@@ -235,35 +237,33 @@ module Rubex
|
|
235
237
|
end
|
236
238
|
|
237
239
|
# specify allocation method in case of attached class
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
240
|
+
next unless top_stmt.is_a?(TopStatement::AttachedKlass)
|
241
|
+
entry = top_stmt.entry
|
242
|
+
scope = top_stmt.scope
|
243
|
+
alloc = ''
|
244
|
+
alloc << "rb_define_alloc_func(#{entry.c_name}, "
|
245
|
+
alloc << "#{scope.find(TopStatement::AttachedKlass::ALLOC_FUNC_NAME).c_name});\n"
|
244
246
|
|
245
|
-
|
246
|
-
end
|
247
|
+
code << alloc
|
247
248
|
end
|
248
249
|
code.nl
|
249
250
|
|
250
251
|
@statements.each do |top_stmt|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
end
|
252
|
+
next unless top_stmt.is_a? TopStatement::Klass
|
253
|
+
entry = @scope.find top_stmt.name
|
254
|
+
klass_scope = entry.type.scope
|
255
|
+
klass_scope.ruby_method_entries.each do |meth|
|
256
|
+
if meth.singleton?
|
257
|
+
code.write_singleton_method klass: entry.c_name,
|
258
|
+
method_name: meth.name, method_c_name: meth.c_name
|
259
|
+
else
|
260
|
+
code.write_instance_method klass: entry.c_name,
|
261
|
+
method_name: meth.name, method_c_name: meth.c_name
|
262
262
|
end
|
263
263
|
end
|
264
264
|
end
|
265
265
|
end
|
266
266
|
end
|
267
|
-
end
|
268
|
-
end
|
269
|
-
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|