<commit_before>#
# Jasy - Web Tooling Framework
# Copyright 2013 <NAME>
#

import copy, re
import jasy.style.parse.Node as Node
import jasy.core.Console as Console


RE_INLINE_VARIABLE = re.compile("\$\{([a-zA-Z0-9\-_\.]+)\}")

MATH_OPERATORS = ("plus", "minus", "mul", "div", "mod")
COMPARE_OPERATORS = ("eq", "ne", "gt", "lt", "ge", "le")

ALL_OPERATORS = MATH_OPERATORS + COMPARE_OPERATORS


class ExecuterError(Exception):
    def __init__(self, message, node):
        Exception.__init__(self, "Variable Error: %s for node type=%s in %s at line %s!" % (message, node.type, node.getFileName(), node.line))




def process(tree):
    __recurser(tree, tree.scope, {})


def __recurser(node, scope, values):
    # 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 not name 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.info("Processing if-condition at %s", node.line)

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

        # Named child "condition" might be replaced so assign variable not before
        conditionNode = node.condition

        if conditionNode.type == "true":
            resultValue = True
        elif conditionNode.type == "false" or conditionNode.type == "null":
            resultValue = False
        elif conditionNode.type in ("number", "string"):
            resultValue = bool(node.condition.value)
        else:
            raise Exception("Unresolved if-block with condition: %s" % conditionNode)

        # Process relevant part of the sub tree
        resultNode = None
        if resultValue is True:
            resultNode = node.thenPart
        elif resultValue is False and hasattr(node, "elsePart"):
            resultNode = node.elsePart

        if resultNode:
            # Fix missing processing of result node
            __recurser(resultNode, scope, values)

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

        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"):
        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)


    # 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":
<commit_msg>Fixed variable resolution scope handling for then/else parts<commit_after>#
# Jasy - Web Tooling Framework
# Copyright 2013 <NAME>
#

import copy, re
import jasy.style.parse.Node as Node
import jasy.core.Console as Console


RE_INLINE_VARIABLE = re.compile("\$\{([a-zA-Z0-9\-_\.]+)\}")

MATH_OPERATORS = ("plus", "minus", "mul", "div", "mod")
COMPARE_OPERATORS = ("eq", "ne", "gt", "lt", "ge", "le")

ALL_OPERATORS = MATH_OPERATORS + COMPARE_OPERATORS


class ExecuterError(Exception):
    def __init__(self, message, node):
        Exception.__init__(self, "Variable Error: %s for node type=%s in %s at line %s!" % (message, node.type, node.getFileName(), node.line))




def process(tree):
    __recurser(tree, tree.scope, {})


def __recurser(node, scope, values):
    # 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 not name 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.info("Processing if-condition at %s", node.line)

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

        # Named child "condition" might be replaced so assign variable not before
        conditionNode = node.condition

        if conditionNode.type == "true":
            resultValue = True
        elif conditionNode.type == "false" or conditionNode.type == "null":
            resultValue = False
        elif conditionNode.type in ("number", "string"):
            resultValue = bool(node.condition.value)
        else:
            raise Exception("Unresolved if-block with condition: %s" % conditionNode)

        # Process relevant part of the sub tree
        resultNode = None
        if resultValue is True:
            resultNode = node.thenPart
        elif resultValue is False and hasattr(node, "elsePart"):
            resultNode = node.elsePart

        if resultNode:
            # Fix missing processing of result node
            __recurser(resultNode, scope, values)

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

        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)


    # 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":

{'fraction_non_alphanumeric': 0.0984788880146866, 'fraction_numerical': 0.0018358248098610018, 'mean_word_length': 2.5858015984955336, 'pattern_counts': {'":': 8, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5191801', 'n_tokens_mistral': 2099, 'n_tokens_neox': 2033, 'n_words': 742}