Beispiel #1
0
 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))
Beispiel #2
0
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)
Beispiel #3
0
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)