-
Notifications
You must be signed in to change notification settings - Fork 1
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