Skip to content

Class Supertype Processing

Tony edited this page May 20, 2019 · 5 revisions

The logic for handling the *superclass instruction is fairly complex so it is written using a kind of Ruby to try to be rigorous, and is hopefully readable.

#----------------------------------------------------------------------------------------------------
# Look below for 'START HERE'
#----------------------------------------------------------------------------------------------------
#
# Some information about a class
#
class Klass
      attr_accessor :id
      attr_accessor :name
      attr_accessor :superclass
      attr_accessor :assign
      attr_accessor :pairs
      attr_accessor :all_inherited_pairs

      def initialize(id, name, superclass, assign, pairs)
            @id = id
            @name = name
            @superclass = superclass
            @assign = assign # A possibly empty or nil array of arrays
            @pairs = pairs # A possibly empty or nil array of pairs
      end
end

#----------------------------------------------------------------------------------------------------
# Function to infer the type that the resulting object should be using the_class and the value_type 
# of the target pair
#----------------------------------------------------------------------------------------------------
def superclass_inference(the_class, value_type)
      top_class = nil

      if the_class.assign.empty?
            #
            # There is no *assign specified, so the value_type of the_pair will determine the type of the result.
            #

            if the_class.all_inherited_pairs.empty?

                  case value_type

                  when 'str'
                        top_class = 'str'
                  when 'num'
                        top_class = 'num'
                  when 'bool'
                        top_class = 'bool'
                  when 'null'
                        top_class = 'null'
                  when 'arr'
                        top_class = 'arr'
                  when 'map'
                        top_class = 'map'
                  end
            else
                  #
                  # If the class contains pairs then the resulting object has to be a map.
                  #
                  top_class = "map"
            end
      else
            #
            # There is a *assign statement so the result must be a map - use the value_type to decide what to do
            #
            top_class = "map"
      end

      return top_class
end

#----------------------------------------------------------------------------------------------------
# START HERE
#----------------------------------------------------------------------------------------------------
# Set this to be the object that represents the class.
#
the_class = Klass.new("a", "b", "c", [["x"], ["x", "y"]], [])


# Set this to be the pair that is to be converted to an instance of the class
the_pair = ''

#
# Determine the type of the right-hand side of the pair we need to convert to an instance of the_class
# E.g. arr, str, map, etc.
#
value_type = get_type_of_pair_value(the_pair)


#
# Follow the chain of superclass statements up the class hierarchy to find the ultimate declared superclass
#
top_class = find_top_superclass(the_class)

if top_class.nil?
      #
      # No superclass is defined in the class hierarchy, so we'll have to use 'superclass inference'
      #
      top_class = superclass_inference(the_class, value_type)
end

#
# We now have a target type for the object we need to create, and the action we take also depends on the
# type of value that we have to convert
#

if value_type.is_a_primitive_type
      #
      # This is the strategy for converting a primitive type to the target type
      #

      case top_class
      when 'str'
            case value_type
            when 'num'
                  quote_the_value
            
            when 'bool'
                  result is "true" or "false"
            else
                  error - if the value is null
            end

      when 'num'
            case value_type
            when 'str'
                  convert string value to num if possible otherwise raise an error.
            
            when 'bool'
                  result is 1 if bool is true, otherwise 0

            else
                  error - if the value is null
            end

      when 'bool'
            # We can only infer this from the value, we can't specify bool, so no conversion in this case.

      when 'null'
            # We can only get here if superclass is not specified and the pair value is null
            result is null

      when 'arr'
            convert to "myClassIdOrName":[ primitive_value]

      when 'map'
            convert_to "myClassIdOrName":{ "value": primitive_value}

      end
else
      #
      # This is the strategy for converting a non-primitive type to the target type.
      #
      # Arrays and maps can consist of complex content so there is no simple way to
      # convert them to a different type - we could take action for specific cases
      # but I think its better to treat consistently as errors.
      #

      case value_type
      when 'arr'

            case top_class
            when 'arr'
                  # Good, its the right type!

            else
                  cannot_convert_arr_to_different_type_so_raise_error

            end

      when 'map'

            case top_class
            when 'map'
                  # Good, its the right type!

            else
                  cannot_convert_map_to_different_type_so_raise_error

            end

      end
end

Clone this wiki locally