Example #1
0
def __recurser(node, permutation, inCondition=False):

    # Support block commands
    # These come with their own node.type
    if node.type == "if":

        # Pre-process condition
        # We manually process each child in for if-types
        __recurser(node.condition, permutation, True)

        # Cast condition to Python boolean type
        resultValue = None
        try:
            resultValue = Operation.castToBool(node.condition)
        except Operation.OperationError as ex:
            Console.debug("Walked into unprocessed condition. Waiting for actual execution. Message: %s", ex)

        if not resultValue is None:

            # Process relevant part of the sub tree
            if resultValue is True:
                # Fix missing processing of result node
                __recurser(node.thenPart, permutation)

                # Finally replace if-node with result node
                node.parent.replace(node, node.thenPart)

            elif resultValue is False and hasattr(node, "elsePart"):
                # Fix missing processing of result node
                __recurser(node.elsePart, permutation)

                # Finally replace if-node with result node
                node.parent.replace(node, node.elsePart)

            else:
                # Cleanup original if-node
                node.parent.remove(node)

            # All done including child nodes
            return


    # Process children first (resolve logic is inner-out)
    for child in list(node):
        if child is not None:
            __recurser(child, permutation, inCondition)


    # Inside of conditions replace identifiers with their actual value (from current permutation)
    if inCondition and node.type == "identifier":
        if not permutation.has(node.value):
            raise ResolverError("Could not find field %s" % node.value, node)

        repl = Util.castNativeToNode(permutation.get(node.value))
        node.parent.replace(node, repl)


    # Support inline @field() commands
    elif node.type == "command" and node.name == "field":
        if len(node.params) == 0:
            raise ResolverError("Missing parameter to insert field via @field.", node)

        identifierNode = node.params[0]
        if identifierNode.type != "identifier":
            raise ResolverError("Invalid parameter to @field call: %s" % identifierNode.type, identifierNode)

        identifier = identifierNode.value
        if not permutation.has(identifier):
            raise ResolverError("Could not find field with the name %s" % identifier, identifierNode)

        repl = Util.castNativeToNode(permutation.get(identifier))
        node.parent.replace(node, repl)


    # Support typical operators
    elif node.type in Util.ALL_OPERATORS:
        repl = Operation.compute(node)
        if repl is not None:
            node.parent.replace(node, repl)
Example #2
0
def __recurser(node, scope, values, profile):
    # Replace variable with actual value
    if node.type == "variable" and not (node.parent.type == "assign"
                                        and node.parent[0] is node):
        name = node.name
        if name not in values:
            raise ExecuterError(
                "Could not resolve variable %s! Missing value!" % name, node)

        value = values[name]
        if value is None:
            raise ExecuterError(
                "Could not resolve variable %s! Value is none!" % name, node)

        Console.debug("Resolving variable: %s at line %s with %s from %s",
                      name, node.line, values[name].type, values[name].line)
        node.parent.replace(node, copy.deepcopy(values[name]))

    # Decide which sub tree of an if-condition is relevant based on current variable situation
    elif node.type == "if":

        Console.debug("Processing if-condition at %s", node.line)

        # Pre-process condition
        # We manually process each child in for if-types
        __recurser(node.condition, scope, values, profile)

        # Cast condition to Python boolean type
        resultValue = Operation.castToBool(node.condition)

        # Process relevant part of the sub tree
        if resultValue is True:
            # Fix missing processing of result node
            __recurser(node.thenPart, scope, values, profile)

            # Finally replace if-node with result node
            node.parent.replace(node, node.thenPart)

        elif resultValue is False and hasattr(node, "elsePart"):
            # Fix missing processing of result node
            __recurser(node.elsePart, scope, values, profile)

            # Finally replace if-node with result node
            node.parent.replace(node, node.elsePart)

        else:
            # Cleanup original if-node
            node.parent.remove(node)

        # Nothing to do here as content is already processed
        return

    # Update scope of new block starts
    if hasattr(node, "scope"):
        relation = getattr(node, "rel", None)

        # Conditional blocks are not exactly blocks in this variable resolution engine
        if not relation in ("thenPart", "elsePart"):
            scope = node.scope
            values = copy.copy(values)
            node.values = values

            # Reset all local variables to None
            # which enforces not to keep values from outer scope
            for name in scope.modified:
                values[name] = None

    # Process children / content
    for child in list(node):
        # Ignore non-children... through possible interactive structure changes
        if child and child.parent is node:
            __recurser(child, scope, values, profile)

    # Update values of variables
    # This happens after processing children to possibly reduce child structure to an easy to assign (aka preprocessed value)
    if (node.type == "declaration"
            and hasattr(node, "initializer")) or node.type == "assign":

        if node.type == "declaration":
            name = node.name
            init = node.initializer
            Console.debug("Found declaration of %s at line %s", name,
                          node.line)

        else:
            name = node[0].name
            init = node[1]
            Console.debug("Found assignment of %s at line %s", name, node.line)

        # Modify value instead of replace when assign operator is set
        if hasattr(node, "assignOp") and node.assignOp is not None:
            if name not in values:
                raise ExecuterError(
                    "Assign operator is not supported as left hand variable is missing: %s"
                    % name, node)

            repl = Operation.compute(node, values[name], init, node.assignOp)
            if repl is not None:
                values[name] = repl

        else:
            # Update internal variable mapping
            # Console.debug("Update value of %s to %s" % (name, init))
            values[name] = init

        # Remove declaration node from tree
        node.parent.remove(node)

    # Support for variables inside property names or selectors
    elif node.type in ("property", "selector") and getattr(
            node, "dynamic", False):

        def replacer(matchObj):
            name = matchObj.group(1)

            if name not in values:
                raise ExecuterError(
                    "Could not resolve variable %s! Missing value!" % name,
                    node)

            value = values[name]
            if value is None:
                raise ExecuterError(
                    "Could not resolve variable %s! Value is none!" % name,
                    node)

            if value.type == "identifier":
                return value.value
            elif value.type == "string":
                return value.value
            elif value.type == "number":
                return "%s%s" % (value.value, getattr(value, "unit", ""))
            else:
                raise ExecuterError(
                    "Could not replace property inline variable with value of type: %s"
                    % value.type, node)

        # Fix all selectors
        if node.type == "selector":
            selectors = node.name
            for pos, selector in enumerate(selectors):
                selectors[pos] = RE_INLINE_VARIABLE.sub(replacer, selector)

        else:
            node.name = RE_INLINE_VARIABLE.sub(replacer, node.name)

    # Execute system commands
    elif node.type == "command":
        repl = Util.executeCommand(node, profile)
        if not repl is node:
            node.parent.replace(node, repl)

    # Support typical operators
    elif node.type in Util.ALL_OPERATORS:
        repl = Operation.compute(node)
        if repl is not None:
            node.parent.replace(node, repl)