rubex 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/CONTRIBUTING.md +73 -9
  4. data/HISTORY.md +19 -0
  5. data/README.md +53 -8
  6. data/REFERENCE.md +112 -44
  7. data/benchmarks/no_gil/no_gil.rb +24 -0
  8. data/benchmarks/no_gil/no_gil.rubex +22 -0
  9. data/bin/rubex +1 -1
  10. data/examples/c_struct_interface/c_struct_interface.rubex +1 -0
  11. data/lib/rubex.rb +1 -0
  12. data/lib/rubex/ast.rb +11 -7
  13. data/lib/rubex/ast/expression.rb +1 -1
  14. data/lib/rubex/ast/expression/actual_arg_list.rb +7 -0
  15. data/lib/rubex/ast/expression/analysed_element_ref/c_var_element_ref.rb +5 -2
  16. data/lib/rubex/ast/expression/analysed_element_ref/ruby_object_element_ref.rb +26 -9
  17. data/lib/rubex/ast/expression/binary/binary_boolean.rb +1 -1
  18. data/lib/rubex/ast/expression/binary/binary_expo.rb +34 -0
  19. data/lib/rubex/ast/expression/binary/colon2.rb +34 -0
  20. data/lib/rubex/ast/expression/binary/empty_classes.rb +0 -3
  21. data/lib/rubex/ast/expression/command_call.rb +24 -0
  22. data/lib/rubex/ast/{statement → expression/command_call}/print.rb +4 -5
  23. data/lib/rubex/ast/{statement → expression/command_call}/raise.rb +29 -24
  24. data/lib/rubex/ast/expression/command_call/require.rb +27 -0
  25. data/lib/rubex/ast/expression/command_call/yield.rb +36 -0
  26. data/lib/rubex/ast/expression/element_ref.rb +10 -5
  27. data/lib/rubex/ast/expression/instance_var.rb +33 -0
  28. data/lib/rubex/ast/expression/method_call.rb +4 -2
  29. data/lib/rubex/ast/expression/method_call/c_function_call.rb +4 -3
  30. data/lib/rubex/ast/expression/method_call/ruby_method_call.rb +7 -5
  31. data/lib/rubex/ast/expression/name.rb +10 -1
  32. data/lib/rubex/ast/expression/ruby_object_element_ref/ruby_array_element_ref.rb +5 -2
  33. data/lib/rubex/ast/expression/ruby_object_element_ref/ruby_hash_element_ref.rb +10 -2
  34. data/lib/rubex/ast/expression/to_ruby_object.rb +1 -0
  35. data/lib/rubex/ast/expression/unary.rb +7 -3
  36. data/lib/rubex/ast/expression/unary_base/ampersand.rb +5 -0
  37. data/lib/rubex/ast/node.rb +213 -185
  38. data/lib/rubex/ast/node/file_node.rb +25 -0
  39. data/lib/rubex/ast/node/main_node.rb +56 -0
  40. data/lib/rubex/ast/statement/begin_block/begin.rb +4 -3
  41. data/lib/rubex/ast/statement/c_array_decl.rb +1 -1
  42. data/lib/rubex/ast/statement/c_ptr_decl.rb +2 -0
  43. data/lib/rubex/ast/statement/no_gil_block.rb +70 -0
  44. data/lib/rubex/ast/statement/return.rb +1 -0
  45. data/lib/rubex/ast/top_statement.rb +1 -1
  46. data/lib/rubex/ast/top_statement/klass.rb +4 -0
  47. data/lib/rubex/ast/top_statement/klass/attached_klass.rb +88 -10
  48. data/lib/rubex/ast/top_statement/method_def.rb +2 -3
  49. data/lib/rubex/ast/top_statement/method_def/c_function_def.rb +10 -4
  50. data/lib/rubex/cli.rb +11 -6
  51. data/lib/rubex/code_supervisor.rb +49 -0
  52. data/lib/rubex/code_writer.rb +22 -1
  53. data/lib/rubex/compiler.rb +109 -30
  54. data/lib/rubex/compiler_config.rb +14 -1
  55. data/lib/rubex/constants.rb +3 -0
  56. data/lib/rubex/data_type.rb +2 -3
  57. data/lib/rubex/data_type/ruby_object/ruby_symbol.rb +0 -1
  58. data/lib/rubex/error.rb +4 -0
  59. data/lib/rubex/helpers/writers.rb +33 -4
  60. data/lib/rubex/lexer.rex +9 -1
  61. data/lib/rubex/lexer.rex.rb +15 -2
  62. data/lib/rubex/parser.racc +125 -49
  63. data/lib/rubex/parser.racc.rb +1526 -1376
  64. data/lib/rubex/rake_task.rb +42 -6
  65. data/lib/rubex/symbol_table/entry.rb +6 -0
  66. data/lib/rubex/symbol_table/scope.rb +28 -3
  67. data/lib/rubex/version.rb +1 -1
  68. data/rubex.gemspec +1 -0
  69. data/spec/basic_ruby_method_spec.rb +2 -2
  70. data/spec/blocks_spec.rb +2 -2
  71. data/spec/box_op_multi_args_spec.rb +34 -0
  72. data/spec/c_function_ptrs_spec.rb +2 -2
  73. data/spec/c_functions_spec.rb +2 -0
  74. data/spec/c_struct_interface_spec.rb +8 -3
  75. data/spec/default_args_spec.rb +2 -2
  76. data/spec/external_c_struct_spec.rb +33 -0
  77. data/spec/fixtures/api/consumer.rubex +0 -0
  78. data/spec/fixtures/api/implementation.rubex +0 -0
  79. data/spec/fixtures/api/implementation.rubexd +0 -0
  80. data/spec/fixtures/box_op_multi_args/box_op_multi_args.rubex +3 -0
  81. data/spec/fixtures/c_functions/c_functions.rubex +13 -0
  82. data/spec/fixtures/c_struct_interface/c_struct_interface.rubex +28 -0
  83. data/spec/fixtures/class_methods/class_methods.rubex +1 -1
  84. data/spec/fixtures/error_handling/error_handling.rubex +2 -2
  85. data/spec/fixtures/external_c_struct/external_c_struct.rubex +16 -0
  86. data/spec/fixtures/if_else/if_else.rubex +1 -1
  87. data/spec/fixtures/init_ruby_objects_with_literal_syntax/init_ruby_objects_with_literal_syntax.rubex +1 -1
  88. data/spec/fixtures/instance_variables/instance_variables.rubex +25 -0
  89. data/spec/fixtures/loops/loops.rubex +2 -2
  90. data/spec/fixtures/module/module.rubex +28 -0
  91. data/spec/fixtures/multi_file_programs/Rakefile +8 -0
  92. data/spec/fixtures/multi_file_programs/a.rubex +5 -0
  93. data/spec/fixtures/multi_file_programs/b.rubex +5 -0
  94. data/spec/fixtures/multi_file_programs/multi_file_programs.rubex +14 -0
  95. data/spec/fixtures/no_gil/no_gil.rubex +24 -0
  96. data/spec/fixtures/no_gil_attach_class/no_gil_attach_class.rubex +23 -0
  97. data/spec/fixtures/no_gil_compile_check/no_gil_compile_check.rubex +4 -0
  98. data/spec/fixtures/outside_stmts/outside_stmts.rubex +6 -0
  99. data/spec/fixtures/pow/pow.rubex +4 -0
  100. data/spec/fixtures/rake_task/single_file/test.rubex +3 -0
  101. data/spec/fixtures/recursion/recursion.rubex +1 -1
  102. data/spec/fixtures/ruby_constant_scoping/ruby_constant_scoping.rubex +7 -0
  103. data/spec/fixtures/ruby_operators/ruby_operators.rubex +1 -1
  104. data/spec/fixtures/ruby_raise/ruby_raise.rubex +2 -2
  105. data/spec/fixtures/ruby_types/ruby_types.rubex +4 -4
  106. data/spec/fixtures/statement_expression/statement_expression.rubex +2 -2
  107. data/spec/fixtures/static_array/static_array.rubex +3 -3
  108. data/spec/fixtures/string_literals/string_literals.rubex +12 -2
  109. data/spec/fixtures/struct/struct.rubex +1 -1
  110. data/spec/fixtures/var_declarations/var_declarations.rubex +1 -1
  111. data/spec/implicit_lib_include_spec.rb +2 -2
  112. data/spec/init_ruby_objects_with_literal_syntax_spec.rb +2 -2
  113. data/spec/instance_variables_spec.rb +33 -0
  114. data/spec/loops_spec.rb +2 -2
  115. data/spec/module_spec.rb +39 -0
  116. data/spec/multi_file_programs_spec.rb +41 -0
  117. data/spec/no_gil_attach_class_spec.rb +33 -0
  118. data/spec/no_gil_compile_check_spec.rb +25 -0
  119. data/spec/no_gil_spec.rb +36 -0
  120. data/spec/outside_stmts_spec.rb +34 -0
  121. data/spec/pow_spec.rb +33 -0
  122. data/spec/rake_task_spec.rb +142 -0
  123. data/spec/recursion_spec.rb +4 -4
  124. data/spec/ruby_constant_scoping_spec.rb +42 -0
  125. data/spec/ruby_raise_spec.rb +2 -2
  126. data/spec/ruby_symbols_spec.rb +2 -2
  127. data/spec/ruby_types_spec.rb +2 -2
  128. data/spec/spec_helper.rb +17 -3
  129. data/spec/string_literals_spec.rb +1 -0
  130. metadata +90 -6
  131. data/lib/rubex/ast/statement/yield.rb +0 -41
@@ -0,0 +1,24 @@
1
+ require 'no_gil.so'
2
+ require 'benchmark'
3
+
4
+ N = 9999999
5
+ Benchmark.bm do |x|
6
+ x.report("with") do
7
+ n = Thread.new { work_with_gil(N) }
8
+ m = Thread.new { work_with_gil(N) }
9
+ o = Thread.new { work_with_gil(N) }
10
+ n.join; m.join; o.join
11
+ end
12
+
13
+ x.report("without") do
14
+ n = Thread.new { work_without_gil(N) }
15
+ m = Thread.new { work_without_gil(N) }
16
+ o = Thread.new { work_without_gil(N) }
17
+ n.join; m.join; o.join
18
+ end
19
+ end
20
+
21
+ # BENCHMARKS
22
+ # user system total real
23
+ # with 2.730000 0.000000 2.730000 ( 2.731592)
24
+ # without 2.990000 0.000000 2.990000 ( 1.076090)
@@ -0,0 +1,22 @@
1
+ cfunc void _work_without_gil(double n) no_gil
2
+ while n > 0 do
3
+ n ** 0.5 + 4
4
+ n -= 1
5
+ end
6
+ end
7
+
8
+ def work_without_gil(n)
9
+ double i = n
10
+ no_gil
11
+ _work_without_gil(i)
12
+ end
13
+
14
+ return i
15
+ end
16
+
17
+ def work_with_gil(double n)
18
+ while n > 0 do
19
+ n ** 0.5 + 4
20
+ n -= 1
21
+ end
22
+ end
data/bin/rubex CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
-
2
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
3
3
  require 'rubex'
4
4
  if Rubex::Cli.all_tasks.keys.include?(ARGV[0]) || ARGV.empty?
5
5
  Rubex::Cli.start
@@ -45,3 +45,4 @@ class Music attach mp3info
45
45
  return data$.mp3info.id
46
46
  end
47
47
  end
48
+
@@ -5,6 +5,7 @@ require 'rubex/error'
5
5
  require 'rubex/ast'
6
6
  require 'rubex/helpers'
7
7
  require 'rubex/code_writer'
8
+ require 'rubex/code_supervisor'
8
9
  require 'rubex/symbol_table'
9
10
  require 'rubex/parser.racc.rb'
10
11
  require 'rubex/compiler_config'
@@ -1,7 +1,11 @@
1
- require 'rubex/helpers'
2
- require 'rubex/ast/statement'
3
- Dir['./lib/rubex/ast/statement/**/*.rb'].sort.each { |f| require f }
4
- require 'rubex/ast/expression'
5
- Dir['./lib/rubex/ast/expression/**/*.rb'].sort.each { |f| require f }
6
- require 'rubex/ast/top_statement'
7
- require 'rubex/ast/node'
1
+ require_relative 'helpers'
2
+ require_relative 'ast/statement'
3
+ require_relative 'ast/expression'
4
+ Dir[File.join(File.dirname(File.dirname(__FILE__)),
5
+ "rubex", "ast", "statement", "**", "*.rb" )].sort.each { |f| require f }
6
+ Dir[File.join(File.dirname(File.dirname(__FILE__)),
7
+ "rubex", "ast", "expression", "**", "*.rb" )].sort.each { |f| require f }
8
+ require_relative 'ast/top_statement'
9
+ require_relative 'ast/node'
10
+ Dir[File.join(File.dirname(File.dirname(__FILE__)),
11
+ "rubex", "ast", "node", "**", "*.rb" )].sort.each { |f| require f }
@@ -14,7 +14,7 @@ module Rubex
14
14
 
15
15
  # If the typecast exists, the typecast is made the overall type of
16
16
  # the expression.
17
- def analyse_types local_scope
17
+ def analyse_types local_scope, extern: false
18
18
  if @typecast
19
19
  @typecast.analyse_types(local_scope)
20
20
  @type = @typecast.type
@@ -27,6 +27,13 @@ module Rubex
27
27
  end
28
28
  end
29
29
 
30
+ def analyse_for_target_type(arg_list, local_scope)
31
+ @args.each_with_index do |arg, i|
32
+ arg.analyse_for_target_type arg_list[i].type, local_scope
33
+ @subexprs << arg
34
+ end
35
+ end
36
+
30
37
  def generate_evaluation_code(code, local_scope)
31
38
  @args.each { |a| a.generate_evaluation_code(code, local_scope) }
32
39
  end
@@ -3,13 +3,16 @@ module Rubex
3
3
  module Expression
4
4
  class CVarElementRef < AnalysedElementRef
5
5
  def analyse_types(local_scope)
6
+ if @pos.size > 1
7
+ raise "C array can only accept 1 arg. Not #{@pos.size}"
8
+ end
6
9
  @pos.analyse_types local_scope
7
10
  @subexprs << @pos
8
11
  end
9
12
 
10
13
  def generate_evaluation_code(code, local_scope)
11
14
  generate_and_dispose_subexprs(code, local_scope) do
12
- @c_code = "#{@entry.c_name}[#{@pos.c_code(local_scope)}]"
15
+ @c_code = "#{@entry.c_name}[#{@pos[0].c_code(local_scope)}]"
13
16
  end
14
17
  end
15
18
 
@@ -19,7 +22,7 @@ module Rubex
19
22
 
20
23
  def generate_assignment_code(rhs, code, local_scope)
21
24
  generate_and_dispose_subexprs(code, local_scope) do
22
- code << "#{@entry.c_name}[#{@pos.c_code(local_scope)}] = "
25
+ code << "#{@entry.c_name}[#{@pos[0].c_code(local_scope)}] = "
23
26
  code << "#{rhs.c_code(local_scope)};"
24
27
  code.nl
25
28
  end
@@ -5,7 +5,7 @@ module Rubex
5
5
  def analyse_types(local_scope)
6
6
  super
7
7
  @has_temp = true
8
- @pos = @pos.to_ruby_object
8
+ @pos.map! { |a| a.to_ruby_object }
9
9
  @pos.allocate_temps local_scope
10
10
  @pos.release_temps local_scope
11
11
  @subexprs << @pos
@@ -13,26 +13,43 @@ module Rubex
13
13
 
14
14
  def generate_evaluation_code(code, local_scope)
15
15
  generate_and_dispose_subexprs(code, local_scope) do
16
- code << "#{@c_code} = rb_funcall(#{@entry.c_name}, rb_intern(\"[]\"), 1, "
17
- code << "#{@pos.c_code(local_scope)});"
16
+ @pos.each { |a| a.generate_evaluation_code(code, local_scope) }
17
+ code << "#{@c_code} = rb_funcall(#{@entry.c_name}, rb_intern(\"[]\"), "
18
+ code << @pos.size.to_s
19
+ @pos.each do |p|
20
+ code << ", #{p.c_code(local_scope)}"
21
+ end
22
+ code << ", NULL" if @pos.empty?
23
+ code << ");"
18
24
  code.nl
19
25
  end
20
26
  end
21
27
 
28
+ # Generate code for calls to array_ref inside structs.
22
29
  def generate_element_ref_code(expr, code, local_scope)
23
30
  generate_and_dispose_subexprs(code, local_scope) do
24
- str = "#{@c_code} = rb_funcall(#{expr.c_code(local_scope)}."
25
- str << "#{@entry.c_name}, rb_intern(\"[]\"), 1, "
26
- str << "#{@pos.c_code(local_scope)});"
27
- code << str
31
+ @pos.each { |a| a.generate_evaluation_code(code, local_scope) }
32
+ code << "#{@c_code} = rb_funcall(#{expr.c_code(local_scope)}."
33
+ code << "#{@entry.c_name}, rb_intern(\"[]\"), #{@pos.size}"
34
+ @pos.each do |p|
35
+ code << ", #{p.c_code(local_scope)}"
36
+ end
37
+ code << ", NULL" if @pos.empty?
38
+ code << ");"
28
39
  code.nl
29
40
  end
30
41
  end
31
42
 
32
43
  def generate_assignment_code(rhs, code, local_scope)
44
+ raise "must specify atleast 1 arg in Object#[]=" if @pos.size < 1
33
45
  generate_and_dispose_subexprs(code, local_scope) do
34
- code << "rb_funcall(#{@entry.c_name}, rb_intern(\"[]=\"), 2,"
35
- code << "#{@pos.c_code(local_scope)}, #{rhs.c_code(local_scope)});"
46
+ @pos.each { |a| a.generate_evaluation_code(code, local_scope) }
47
+ code << "rb_funcall(#{@entry.c_name}, rb_intern(\"[]=\"),"
48
+ code << "#{@pos.size + 1}"
49
+ @pos.each do |p|
50
+ code << ", #{p.c_code(local_scope)}"
51
+ end
52
+ code << ", #{rhs.c_code(local_scope)});"
36
53
  code.nl
37
54
  end
38
55
  end
@@ -4,7 +4,7 @@ module Rubex
4
4
  class BinaryBoolean < Binary
5
5
  def analyse_types(local_scope)
6
6
  @left.analyse_types local_scope
7
- @right.analyse_types local_scope
7
+ @right.analyse_for_target_type @left.type, local_scope
8
8
  if type_of(@left).object? || type_of(@right).object?
9
9
 
10
10
  @left = @left.to_ruby_object
@@ -0,0 +1,34 @@
1
+ module Rubex
2
+ module AST
3
+ module Expression
4
+ class BinaryExpo < Binary
5
+ def analyse_types(local_scope)
6
+ @left.analyse_types local_scope
7
+ @right.analyse_types local_scope
8
+ if type_of(@left).object? || type_of(@right).object?
9
+ @left = @left.to_ruby_object
10
+ @right = @right.to_ruby_object
11
+ @subexprs << @left
12
+ @subexprs << @right
13
+ else
14
+ @type = Rubex::DataType::F64.new
15
+ end
16
+
17
+ end
18
+
19
+ def generate_evaluation_code code, local_scope
20
+ generate_and_dispose_subexprs(code, local_scope) do
21
+ if @type.object?
22
+ code << "#{@c_code} = rb_funcall(#{@left.c_code(local_scope)}," +
23
+ "rb_intern(\"#{@operator}\")," +
24
+ "1, #{@right.c_code(local_scope)});"
25
+ code.nl
26
+ else
27
+ @c_code = "( pow(#{@left.c_code(local_scope)}, #{@right.c_code(local_scope)}) )"
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ module Rubex
2
+ module AST
3
+ module Expression
4
+ class Colon2 < Base
5
+ attr_reader :lhs, :rhs
6
+
7
+ def initialize lhs, rhs
8
+ @lhs = lhs
9
+ @rhs = rhs
10
+ end
11
+
12
+ def analyse_types local_scope
13
+ @type = DataType::RubyObject.new
14
+ end
15
+
16
+ def generate_evaluation_code code, local_scope
17
+ @c_code = recursive_scoping_generation @lhs, @rhs, "rb_const_get(CLASS_OF(#{local_scope.self_name}), rb_intern(\"#{@lhs}\"))"
18
+ end
19
+
20
+ def recursive_scoping_generation lhs, rhs, c_str
21
+ if rhs.is_a?(Colon2)
22
+ recursive_scoping_generation rhs.lhs, rhs.rhs, "rb_const_get(#{c_str}, rb_intern(\"#{rhs.lhs}\"))"
23
+ else
24
+ "rb_const_get(#{c_str}, rb_intern(\"#{rhs}\"))"
25
+ end
26
+ end
27
+
28
+ def c_code local_scope
29
+ super + @c_code
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -13,9 +13,6 @@ module Rubex
13
13
  class BinaryDivide < Binary
14
14
  end
15
15
 
16
- class BinaryExpo < Binary
17
- end
18
-
19
16
  class BinaryMod < Binary
20
17
  end
21
18
 
@@ -57,11 +57,35 @@ module Rubex
57
57
  @entry && @entry.type.base_type.c_function?
58
58
  end
59
59
 
60
+ def raise_call?
61
+ !@entry && @command == "raise"
62
+ end
63
+
64
+ def yield_call?
65
+ !@entry && @command == "yield"
66
+ end
67
+
68
+ def print_call?
69
+ !@entry && @command == "print"
70
+ end
71
+
72
+ def require_call?
73
+ !@entry && @command == "require"
74
+ end
75
+
60
76
  def analyse_command_type(local_scope)
61
77
  if struct_member_call?
62
78
  @command = Expression::StructOrUnionMemberCall.new @expr, @command, @arg_list
63
79
  elsif c_function_call?
64
80
  @command = Expression::CFunctionCall.new @expr, @command, @arg_list
81
+ elsif raise_call?
82
+ @command = Expression::Raise.new @arg_list
83
+ elsif yield_call?
84
+ @command = Expression::Yield.new @arg_list
85
+ elsif print_call?
86
+ @command = Expression::Print.new @arg_list
87
+ elsif require_call?
88
+ @command = Expression::Require.new @arg_list
65
89
  else
66
90
  @command = Expression::RubyMethodCall.new @expr, @command, @arg_list
67
91
  end
@@ -1,13 +1,12 @@
1
1
  module Rubex
2
2
  module AST
3
- module Statement
3
+ module Expression
4
4
  class Print < Base
5
- def initialize(expressions, location)
6
- super(location)
5
+ def initialize(expressions)
7
6
  @expressions = expressions
8
7
  end
9
8
 
10
- def analyse_statement(local_scope)
9
+ def analyse_types(local_scope)
11
10
  @expressions.each do |expr|
12
11
  expr.analyse_types local_scope
13
12
  expr.allocate_temps local_scope
@@ -15,7 +14,7 @@ module Rubex
15
14
  end
16
15
  end
17
16
 
18
- def generate_code(code, local_scope)
17
+ def generate_evaluation_code(code, local_scope)
19
18
  super
20
19
  @expressions.each do |expr|
21
20
  expr.generate_evaluation_code code, local_scope
@@ -1,44 +1,49 @@
1
1
  module Rubex
2
2
  module AST
3
- module Statement
4
- class Raise < Base
3
+ module Expression
4
+ class Raise < CommandCall
5
5
  def initialize(args)
6
6
  @args = args
7
7
  end
8
8
 
9
- def analyse_statement(local_scope)
9
+ def analyse_types(local_scope)
10
10
  @args.analyse_types local_scope
11
11
  @args.allocate_temps local_scope
12
- @args.release_temps local_scope
13
12
  unless @args.empty? || @args[0].is_a?(AST::Expression::Name) ||
14
13
  @args[0].is_a?(AST::Expression::Literal::StringLit)
15
14
  raise Rubex::TypeMismatchError, "Wrong argument list #{@args.inspect} for raise."
16
15
  end
16
+ @subexprs = [@args]
17
+ @args.release_temps local_scope
17
18
  end
18
19
 
19
- def generate_code(code, local_scope)
20
- @args.generate_evaluation_code code, local_scope
21
- str = ''
22
- str << 'rb_raise('
20
+ def generate_evaluation_code(code, local_scope)
21
+ generate_and_dispose_subexprs(code, local_scope) do
22
+ @c_code = ''
23
+ @c_code << 'rb_raise('
23
24
 
24
- if @args[0].is_a?(AST::Expression::Name)
25
- str << @args[0].c_code(local_scope) + ','
26
- args = @args[1..-1]
27
- else
28
- str << Rubex::DEFAULT_CLASS_MAPPINGS['RuntimeError'] + ','
29
- args = @args
30
- end
25
+ if @args[0].is_a?(AST::Expression::Name)
26
+ @c_code << @args[0].c_code(local_scope) + ','
27
+ args = @args[1..-1]
28
+ else
29
+ @c_code << Rubex::DEFAULT_CLASS_MAPPINGS['RuntimeError'] + ','
30
+ args = @args
31
+ end
31
32
 
32
- unless args.empty?
33
- str << "\"#{prepare_format_string(args)}\" ,"
34
- str << args.map { |arg| (inspected_expr(arg, local_scope)).to_s }.join(',')
35
- else
36
- str << '""'
33
+ unless args.empty?
34
+ @c_code << "\"#{prepare_format_string(args)}\" ,"
35
+ @c_code << args.map { |arg| (inspected_expr(arg, local_scope)).to_s }.join(',')
36
+ else
37
+ @c_code << '""'
38
+ end
39
+ @c_code << ');'
37
40
  end
38
- str << ');'
39
- code << str
40
- code.nl
41
- @args.generate_disposal_code code
41
+ end
42
+
43
+ def generate_disposal_code(code); end
44
+
45
+ def c_code(_local_scope)
46
+ super + @c_code
42
47
  end
43
48
 
44
49
  private
@@ -0,0 +1,27 @@
1
+ module Rubex
2
+ module AST
3
+ module Expression
4
+ class Require < Base
5
+ def initialize args
6
+ @args = args
7
+ end
8
+
9
+ def analyse_types(local_scope)
10
+ raise "require can only support single string argument." if @args.size > 1
11
+ if !@args[0].is_a?(Expression::Literal::StringLit)
12
+ raise "Argument to require must be a string literal. not #{@args[0].class}."
13
+ end
14
+ end
15
+
16
+ def generate_evaluation_code(code, local_scope)
17
+ string = @args[0].instance_variable_get(:@name)
18
+ @c_code = "rb_funcall(rb_cObject, rb_intern(\"require\"), 1, rb_str_new2(\"#{string}\"))"
19
+ end
20
+
21
+ def c_code(_local_scope)
22
+ @c_code
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end