Class: C::BinaryExpression

Inherits:
Object
  • Object
show all
Defined in:
lib/csquare.rb

Instance Method Summary collapse

Instance Method Details

#depthObject

Determine the depth of this tree of binary expressions. Only include BinaryExpression nodes.



1058
1059
1060
1061
1062
# File 'lib/csquare.rb', line 1058

def depth
  left_depth = expr1.respond_to?(:depth) ? expr1.depth : 0
  right_depth = expr2.respond_to?(:depth) ? expr2.depth : 0
  (left_depth > right_depth ? left_depth : right_depth) + 1
end

#involves_on_left?(literal_or_variables) ⇒ Boolean

Returns:

  • (Boolean)


1065
1066
1067
1068
# File 'lib/csquare.rb', line 1065

def involves_on_left? literal_or_variables
  return expr1.involves?(literal_or_variables) if expr1.Expression?
  false
end

#involves_on_right?(literal_or_variables) ⇒ Boolean

Returns:

  • (Boolean)


1070
1071
1072
1073
# File 'lib/csquare.rb', line 1070

def involves_on_right? literal_or_variables
  return expr2.involves?(literal_or_variables) if expr2.Expression?
  false
end

#recombine!(function, blueprint, type_symbol, return_type) ⇒ Object

Replace some expression with the pattern from Blueprint.



998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
# File 'lib/csquare.rb', line 998

def recombine! function, blueprint, type_symbol, return_type

  # Get depth before we recombine children
  d = depth

  local_return_type = self.return_typename(function, blueprint)
  return_type ||= local_return_type
  return_type = local_return_type if local_return_type == :boolean


  # Upgrade the return type for expressions that aren't simple
  final_return_type = (d > 1 && return_type == blueprint.key) ? blueprint.long_key : return_type

  args_types = {}

  first_field_type = nil # type which the templater recognizes for the right-hand argument

  self.fields.each_with_index do |f,i|

    # Get the node
    n = self.send(f.reader)

    # n_result: ast, return type (or just nil)
    n_result = n.recombine! function, blueprint, type_symbol, final_return_type

    first_field_type = n_result[1] if i == 0

    # Basically this says: don't do it for boolean binary expressions
    if blueprint.responds_to_typename?(first_field_type)

      if blueprint.has_op?(self.op) && final_return_type.is_a?(String) && (d > 1 || final_return_type != n_result[1]) && n_result[0].depth > 0

        # TODO: Reusable temp locals (e.g., temp0, temp1, temp2, ...) for better -O0 performance
        #if blueprint.id == :rational && function.name =~ /^numbmm/
        #  require 'pry'
        #  binding.pry
        #end

        temp = self.new_temp_local(final_return_type)
        self.new_temp_statement("#{temp} = #{n_result[0].csquare_key}", self.parent_stmt)

        n_result[0] = C::Expression.parse(temp)
      end

      args_types[n_result[0].csquare_key] = n_result[1]

    end

    replace_node(n, n_result[0]) unless n == n_result[0]
  end


  result = if blueprint.has_op?(op) && blueprint.responds_to_typename?(first_field_type)
    blueprint.decorated_expression(type_symbol, self.op, args_types, final_return_type)
  end

  result.nil? ? [self, local_return_type] : result
end

#return_typename(function, blueprint) ⇒ Object

Which type should we expect this binary expression to return?

Needed for determining template-based mutations.



1078
1079
1080
1081
# File 'lib/csquare.rb', line 1078

def return_typename function, blueprint
  return :boolean if CSquare::Generator::BOOL_CAST_TO_OP.has_key?(self.class)
  self.expr1.return_typename(function, blueprint)
end