/lib/rubex/ast/expression/name.rb

https://github.com/SciRuby/rubex · Ruby · 136 lines · 108 code · 15 blank · 13 comment · 12 complexity · 98c09b8ceb6a267d7f0120810e46e95c MD5 · raw file

  1. module Rubex
  2. module AST
  3. module Expression
  4. # Singular name node with no sub expressions.
  5. class Name < Base
  6. def initialize(name)
  7. @name = name
  8. end
  9. # Used when the node is a LHS of an assign statement.
  10. def analyse_declaration(_rhs, local_scope)
  11. @entry = local_scope.find @name
  12. unless @entry
  13. local_scope.add_ruby_obj(name: @name, c_name: Rubex::VAR_PREFIX + @name, value: @rhs)
  14. @entry = local_scope[@name]
  15. end
  16. @type = @entry.type
  17. end
  18. def analyse_for_target_type(target_type, local_scope)
  19. @entry = local_scope.find @name
  20. if @entry&.type&.c_function? && target_type.c_function_ptr?
  21. @type = @entry.type
  22. else
  23. analyse_types local_scope
  24. end
  25. end
  26. # Analyse a Name node. This can either be a variable name or a method call
  27. # without parenthesis. Code in this method that creates a RubyMethodCall
  28. # node primarily exists because in Ruby methods without arguments can
  29. # be called without parentheses. These names can potentially be Ruby
  30. # methods that are not visible to Rubex, but are present in the Ruby
  31. # run time. For example, a program like this:
  32. #
  33. # def foo
  34. # bar
  35. # #^^^ this is a name node
  36. # end
  37. def analyse_types(local_scope)
  38. @entry = local_scope.find @name
  39. unless @entry
  40. if ruby_constant?
  41. analyse_as_ruby_constant local_scope
  42. else
  43. add_as_ruby_method_to_scope local_scope
  44. end
  45. end
  46. assign_type_based_on_whether_wrapped_type
  47. analyse_as_ruby_method(local_scope) if @entry.type.ruby_method?
  48. analyse_as_c_function(local_scope) if @entry.type.c_function?
  49. if @name.is_a?(Expression::Base)
  50. @name.allocate_temps local_scope
  51. @name.release_temps local_scope
  52. end
  53. super
  54. end
  55. def analyse_as_c_function(local_scope)
  56. @name = Rubex::AST::Expression::CFunctionCall.new(
  57. Expression::Self.new, @name,
  58. Expression::ActualArgList.new([])
  59. )
  60. @name.analyse_types(local_scope)
  61. end
  62. def generate_evaluation_code(code, local_scope)
  63. if @name.respond_to? :generate_evaluation_code
  64. @name.generate_evaluation_code code, local_scope
  65. end
  66. end
  67. def generate_disposal_code(code)
  68. if @name.respond_to? :generate_disposal_code
  69. @name.generate_disposal_code code
  70. end
  71. end
  72. def generate_assignment_code(rhs, code, local_scope)
  73. code << "#{c_code(local_scope)} = #{rhs.c_code(local_scope)};"
  74. code.nl
  75. rhs.generate_disposal_code code
  76. end
  77. def c_code(local_scope)
  78. code = super
  79. code <<
  80. if @name.is_a?(Rubex::AST::Expression::Base)
  81. @name.c_code(local_scope)
  82. else
  83. @entry.c_name
  84. end
  85. code
  86. end
  87. private
  88. def ruby_constant?
  89. @name[0].match(/[A-Z]/)
  90. end
  91. def analyse_as_ruby_constant(local_scope)
  92. @name = Expression::RubyConstant.new @name
  93. @name.analyse_types local_scope
  94. @entry = @name.entry
  95. end
  96. def add_as_ruby_method_to_scope(local_scope)
  97. @entry = local_scope.add_ruby_method(
  98. name: @name,
  99. c_name: @name,
  100. extern: true,
  101. scope: nil,
  102. arg_list: Expression::ActualArgList.new([])
  103. )
  104. end
  105. def analyse_as_ruby_method(local_scope)
  106. @name = Rubex::AST::Expression::RubyMethodCall.new(
  107. Expression::Self.new, @name, Expression::ActualArgList.new([])
  108. )
  109. @name.analyse_types local_scope
  110. end
  111. def assign_type_based_on_whether_wrapped_type
  112. if @entry.type.alias_type? || @entry.type.ruby_method? || @entry.type.c_function?
  113. @type = @entry.type.type
  114. else
  115. @type = @entry.type
  116. end
  117. end
  118. end
  119. end
  120. end
  121. end