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