def parse_string(self, expr): str_id, actions = action4.get_string_action4s(0, 0xD0, expr) self.extra_actions.extend(actions) self.parse_constant(expression.ConstantNumeric(str_id))
def parse_property(prop_info, value_list, feature, id): """ Parse a single property @param prop_info: A dictionary with property information @type prop_info: C{dict} @param value_list: List of values for the property, with unit conversion applied @type value_list: C{list} of L{Expression} @param feature: Feature of the associated item @type feature: C{int} @param id: ID of the associated item @type id: L{Expression} @return: A tuple containing the following: - List of properties to add to the action 0 - List of actions to prepend - List of modifications to apply via action 6 - List of actions to append @rtype: C{tuple} of (C{list} of L{Action0Property}, C{list} of L{BaseAction}, C{list} of 3-C{tuple}, C{list} of L{BaseAction}) """ action_list = [] action_list_append = [] mods = [] if 'custom_function' in prop_info: props = prop_info['custom_function'](*value_list) else: # First process each element in the value_list final_values = [] for i, value in enumerate(value_list): if 'string_literal' in prop_info and ( isinstance(value, expression.StringLiteral) or prop_info['string_literal'] != 4): # Parse non-string exprssions just like integers. User will have to take care of proper value. # This can be used to set a label (=string of length 4) to the value of a parameter. if not isinstance(value, expression.StringLiteral): raise generic.ScriptError( "Value for property {:d} must be a string literal". format(prop_info['num']), value.pos) if len(value.value) != prop_info['string_literal']: raise generic.ScriptError( "Value for property {:d} must be of length {:d}". format(prop_info['num'], prop_info['string_literal']), value.pos) elif isinstance(value, expression.ConstantNumeric): pass elif isinstance(value, expression.Parameter) and isinstance( value.num, expression.ConstantNumeric): mods.append((value.num.value, prop_info['size'], i * prop_info['size'] + 1)) value = expression.ConstantNumeric(0) elif isinstance(value, expression.String): if not 'string' in prop_info: raise generic.ScriptError( "String used as value for non-string property: " + str(prop_info['num']), value.pos) string_range = prop_info['string'] stringid, string_actions = action4.get_string_action4s( feature, string_range, value, id) value = expression.ConstantNumeric(stringid) action_list_append.extend(string_actions) else: tmp_param, tmp_param_actions = actionD.get_tmp_parameter(value) mods.append( (tmp_param, prop_info['size'], i * prop_info['size'] + 1)) action_list.extend(tmp_param_actions) value = expression.ConstantNumeric(0) final_values.append(value) # Now, write a single Action0 Property with all of these values if prop_info['num'] != -1: props = [ Action0Property(prop_info['num'], final_values, prop_info['size']) ] else: props = [] return (props, action_list, mods, action_list_append)
def parse_result(value, action_list, act6, offset, parent_action, none_result, var_range, repeat_result=1): """ Parse a result (another switch or CB result) in a switch block. @param value: Value to parse @type value: L{Expression} @param action_list: List to append any extra actions to @type action_list: C{list} of L{BaseAction} @param act6: Action6 to add any modifications to @type act6: L{Action6} @param offset: Current offset to use for action6 @type offset: C{int} @param parent_action: Reference to the action of which this is a result @type parent_action: L{BaseAction} @param none_result: Result to use to return the computed value @type none_result: L{Expression} @param var_range: Variable range to use for variables in the expression @type var_range: C{int} @param repeat_result: Repeat any action6 modifying of the next sprite this many times. @type repeat_result: C{int} @return: A tuple of two values: - The value to use as return value - Comment to add to this value @rtype: C{tuple} of (L{ConstantNumeric} or L{SpriteGroupRef}), C{str} """ if value is None: comment = "return;" assert none_result is not None if isinstance(none_result, expression.SpriteGroupRef): result = parse_sg_ref_result(none_result, action_list, parent_action, var_range) else: result = none_result elif isinstance(value, expression.SpriteGroupRef): result = parse_sg_ref_result(value, action_list, parent_action, var_range) comment = result.name.value + ";" elif isinstance(value, expression.ConstantNumeric): comment = "return {:d};".format(value.value) result = value if not (-16384 <= value.value <= 32767): msg = ( "Callback results are limited to -16384..16383 (when the result is a signed number)" " or 0..32767 (unsigned), encountered {:d}.").format( value.value) raise generic.ScriptError(msg, value.pos) elif isinstance(value, expression.String): comment = "return {};".format(str(value)) str_id, actions = action4.get_string_action4s(0, 0xD0, value) action_list.extend(actions) result = expression.ConstantNumeric(str_id - 0xD000 + 0x8000) elif value.supported_by_actionD(False): tmp_param, tmp_param_actions = actionD.get_tmp_parameter( nmlop.OR(value, 0x8000).reduce()) comment = "return param[{:d}];".format(tmp_param) action_list.extend(tmp_param_actions) for i in range(repeat_result): act6.modify_bytes(tmp_param, 2, offset + 2 * i) result = expression.ConstantNumeric(0) else: global return_action_id extra_actions, result = create_return_action( value, parent_action.feature, "@return_action_{:d}".format(return_action_id), var_range) return_action_id += 1 action2.add_ref(result, parent_action) action_list.extend(extra_actions) comment = "return {}".format(value) return (result, comment)