Ejemplo n.º 1
0
def reduceOperation(literalNode):

    resultNode = literalNode
    treeModified = False

    # can only reduce with constants
    if literalNode.type != "constant":
        return literalNode, False

    # check if we're in an operation
    ngParent = nextNongroupParent(literalNode)  # could be operand in ops
    if not ngParent or ngParent.type != "operation":
        return literalNode, False
    else:
        operationNode = ngParent

    # try to evaluate expr
    operationNode = evaluate.evaluate(operationNode)
    if operationNode.evaluated != ():  # we have a value
        # create replacement
        resultNode = symbol("constant")(operationNode.get("line"),
                                        operationNode.get("column"))
        resultNode = set_node_type_from_value(resultNode,
                                              operationNode.evaluated)
        # modify tree
        operationNode.parent.replaceChild(operationNode, resultNode)
        treeModified = True

    return resultNode, treeModified
Ejemplo n.º 2
0
def prefix(id_):
    def format(self, optns, state):
        r = self.commentsPretty(optns, state)
        r += self.get("value")
        r += self.getChild("first").format(optns, state)
        return r
    symbol(id_).format = format
Ejemplo n.º 3
0
def reduceOperation(literalNode): 

    resultNode = literalNode
    treeModified = False

    # can only reduce with constants
    if literalNode.type != "constant":
        return literalNode, False

    # check if we're in an operation
    ngParent = nextNongroupParent(literalNode) # could be operand in ops
    if not ngParent or ngParent.type != "operation":
        return literalNode, False
    else:
        operationNode = ngParent

    # try to evaluate expr
    operationNode = evaluate.evaluate(operationNode)
    if operationNode.evaluated != (): # we have a value
        # create replacement
        resultNode = symbol("constant")(
            operationNode.get("line"), operationNode.get("column"))
        resultNode = set_node_type_from_value(resultNode, operationNode.evaluated)
        # modify tree
        operationNode.parent.replaceChild(operationNode, resultNode)
        treeModified = True

    return resultNode, treeModified
Ejemplo n.º 4
0
def reduceCall(callNode, value):
    # construct the value node
    valueNode = symbol("constant")(callNode.get("line"),
                                   callNode.get("column"))
    valueNode.set("value", str(value))
    if isinstance(value, types.StringTypes):
        valueNode.set("constantType", "string")
        valueNode.set("detail", "doublequotes")
    # this has to come first, as isinstance(True, types.IntType) is also true!
    elif isinstance(value, types.BooleanType):
        valueNode.set("constantType", "boolean")
        valueNode.set("value", str(value).lower())
    elif isinstance(value, types.IntType):
        valueNode.set("constantType", "number")
        valueNode.set("detail", "int")
    elif isinstance(value, types.FloatType):
        valueNode.set("constantType", "number")
        valueNode.set("detail", "float")
    elif isinstance(value, types.NoneType):
        valueNode.set("constantType", "null")
        valueNode.set("value", "null")
    else:
        raise ValueError("Illegal value for JS constant: %s" % str(value))
    # put it in place of the callNode
    #print "optimizing: .get()"
    callNode.parent.replaceChild(callNode, valueNode)
    return valueNode
Ejemplo n.º 5
0
 def prefix(id_):
     def visit_(self, optns, state):
         r = self.commentsPretty(self.comments, optns, state)
         r += self.get("value")
         r += self.getChild(0).format(optns, state)
         return r
     symbol(id_).format = format
Ejemplo n.º 6
0
def prefix(id_):
    def toPretty(self, optns, state):
        r = u''
        r += self.get("value")
        r += self.getChild("first").toPretty(optns, state)
        return r
    symbol(id_).toPretty = toPretty
Ejemplo n.º 7
0
def reduceCall(callNode, value):
    # construct the value node
    valueNode = symbol("constant")(
            callNode.get("line"), callNode.get("column"))
    valueNode.set("value", str(value))
    if isinstance(value, types.StringTypes):
        valueNode.set("constantType","string")
        valueNode.set("detail", "doublequotes")
    # this has to come first, as isinstance(True, types.IntType) is also true!
    elif isinstance(value, types.BooleanType):
        valueNode.set("constantType","boolean")
        valueNode.set("value", str(value).lower())
    elif isinstance(value, types.IntType):
        valueNode.set("constantType","number")
        valueNode.set("detail", "int")
    elif isinstance(value, types.FloatType):
        valueNode.set("constantType","number")
        valueNode.set("detail", "float")
    elif isinstance(value, types.NoneType):
        valueNode.set("constantType","null")
        valueNode.set("value", "null")
    else:
        raise ValueError("Illegal value for JS constant: %s" % str(value))
    # put it in place of the callNode
    #print "optimizing: .get()"
    callNode.parent.replaceChild(callNode, valueNode)
    return valueNode
Ejemplo n.º 8
0
 def visit_ArrayExpression(self, enode):  # array literal
     n = new_symbol("array", enode)
     for child in enode["elements"]:
         if child is None:
             n.childappend(symbol("(empty)")())
         else:
             n.childappend(self.visit_Expression(child))
     return n
Ejemplo n.º 9
0
def prefix_v(id_):
    def toPretty(self, optns, state):
        r = self.commentsPretty(optns, state)
        r += self.get("value")
        r += self.space()
        r += self.getChild("first").toPretty(optns, state)
        return r
    symbol(id_).toPretty = toPretty
Ejemplo n.º 10
0
 def visit_ArrayExpression(self, enode): # array literal
     n = new_symbol("array", enode)
     for child in enode["elements"]:
         if child is None:
             n.childappend(symbol("(empty)")())
         else:
             n.childappend(self.visit_Expression(child))
     return n
Ejemplo n.º 11
0
def prefix(id_):
    def format(self, optns, state):
        r = self.commentsPretty(optns, state)
        r += self.get("value")
        r += self.getChild(0).format(optns, state)
        return r

    symbol(id_).format = format
Ejemplo n.º 12
0
def reduceCall(callNode, value):
    # construct the value node
    valueNode = symbol("constant")(callNode.get("line"), callNode.get("column"))
    valueNode = reducer.set_node_type_from_value(valueNode, value)
    # put it in place of the callNode
    # print "optimizing: .get()"
    callNode.parent.replaceChild(callNode, valueNode)
    return valueNode
Ejemplo n.º 13
0
def prefix_v(id_):
    def format(self, optns, state):
        r = self.commentsPretty(optns, state)
        r += self.get("value")
        r += self.space()
        r += self.getChild(0).format(optns, state)
        return r
    symbol(id_).format = format
Ejemplo n.º 14
0
def reduceCall(callNode, value):
    # construct the value node
    valueNode = symbol("constant")(callNode.get("line"),
                                   callNode.get("column"))
    valueNode = reducer.set_node_type_from_value(valueNode, value)
    # put it in place of the callNode
    #print "optimizing: .get()"
    callNode.parent.replaceChild(callNode, valueNode)
    return valueNode
Ejemplo n.º 15
0
def prefix_v(id_):
    def toPretty(self, optns, state):
        r = self.commentsPretty(optns, state)
        r += self.get("value")
        r += self.space()
        r += self.getChild("first").toPretty(optns, state)
        return r

    symbol(id_).toPretty = toPretty
Ejemplo n.º 16
0
    def prefix_v(id_):
        def visit_(self, optns, state):
            r = self.commentsPretty(self.comments, optns, state)
            r += self.get("value")
            r += self.space()
            r += self.getChild(0).format(optns, state)
            return r

        symbol(id_).format = format
Ejemplo n.º 17
0
def infix(id_):
    def format(self, optns, state):
        r = self.commentsPretty(optns, state)
        r += self.getChild(0).format(optns, state)
        r += ' '
        r += self.get("value")
        r += ' '
        r += self.getChild(1).format(optns, state)
        return r
    symbol(id_).format = format
Ejemplo n.º 18
0
 def infix_v(id_):
     def visit_(self, optns, state):  # adapt the output
         r = self.commentsPretty(self.comments, optns, state)
         r += self.getChild(0).format(optns, state)
         r += self.space()
         r += self.get("value")
         r += self.space()
         r += self.getChild(1).format(optns, state)
         return r
     symbol(id_).format = format
Ejemplo n.º 19
0
def infix(id_):
    def toPretty(self, optns, state):
        r = self.commentsPretty(optns, state)
        r += self.getChild("first").toPretty(optns, state)
        r += ' '
        r += self.get("value")
        r += ' '
        r += self.getChild("second").toPretty(optns, state)
        return r
    symbol(id_).toPretty = toPretty
Ejemplo n.º 20
0
def infix_v(id_):
    def toPretty(self, optns, state):  # adapt the output
        r = u''
        r += self.getChild("first").toPretty(optns, state)
        r += self.space()
        r += self.get("value")
        r += self.space()
        r += self.getChild("second").toPretty(optns, state)
        return r
    symbol(id_).toPretty = toPretty
Ejemplo n.º 21
0
def infix_v(id_):
    def format(self, optns, state):  # adapt the output
        r = self.commentsPretty(optns, state)
        r += self.getChild("first").format(optns, state)
        r += self.space()
        r += self.get("value")
        r += self.space()
        r += self.getChild("second").format(optns, state)
        return r
    symbol(id_).format = format
Ejemplo n.º 22
0
def infix_v(id_):
    def format(self, optns, state):  # adapt the output
        r = self.commentsPretty(optns, state)
        r += self.getChild(0).format(optns, state)
        r += self.space()
        r += self.get("value")
        r += self.space()
        r += self.getChild(1).format(optns, state)
        return r

    symbol(id_).format = format
Ejemplo n.º 23
0
def infix(id_):
    def toPretty(self, optns, state):
        r = self.commentsPretty(optns, state)
        r += self.getChild("first").toPretty(optns, state)
        r += ' '
        r += self.get("value")
        r += ' '
        r += self.getChild("second").toPretty(optns, state)
        return r

    symbol(id_).toPretty = toPretty
Ejemplo n.º 24
0
 def _visit_monadic(self, node, operator):
     op1 = node.children[0]
     nnode = node
     if hasattr(op1, "evaluated"):
         if operator in self.operations:
             evaluated = self.operations[operator](op1.evaluated)
             nnode = symbol("constant")(
                 node.get("line"), node.get("column"))
             set_node_type_from_value(nnode, evaluated)
             nnode.evaluated = evaluated
     return nnode
Ejemplo n.º 25
0
    def infix(id_):
        def visit_(self, optns, state):
            r = self.commentsPretty(self.comments, optns, state)
            r += self.getChild(0).format(optns, state)
            r += ' '
            r += self.get("value")
            r += ' '
            r += self.getChild(1).format(optns, state)
            return r

        symbol(id_).format = format
Ejemplo n.º 26
0
 def _visit_monadic(self, node, operator):
     op1 = node.children[0]
     nnode = node
     if hasattr(op1, "evaluated"):
         if operator in self.operations:
             evaluated = self.operations[operator](op1.evaluated)
             if evaluated != ():
                 nnode = symbol("constant")(node.get("line"),
                                            node.get("column"))
                 set_node_type_from_value(nnode, evaluated)
                 nnode.evaluated = evaluated
     return nnode
Ejemplo n.º 27
0
def prepostfix(id_):  # pre-/post-fix operators (++, --)
    def format(self, optns, state):
        r = self.commentsPretty(optns, state)
        operator = self.get("value")
        operand = self.getChild("first").format(optns, state)
        r += self.get("value")
        if self.get("left", '') == "true":
            r = [operator, operand]
        else:
            r = [operand, operator]
        return u''.join(r)
    symbol(id_).format = format
Ejemplo n.º 28
0
def prepostfix(id_):  # pre-/post-fix operators (++, --)
    def toPretty(self, optns, state):
        r = u''
        operator = self.get("value")
        operand = self.getChild("first").toPretty(optns, state)
        r += self.get("value")
        if self.get("left", '') == "true":
            r = [operator, operand]
        else:
            r = [operand, operator]
        return u''.join(r)
    symbol(id_).toPretty = toPretty
Ejemplo n.º 29
0
def prepostfix(id_):  # pre-/post-fix operators (++, --)
    def toPretty(self, optns, state):
        r = u""
        operator = self.get("value")
        operand = self.getChild("first").toPretty(optns, state)
        r += self.get("value")
        if self.get("left", "") == "true":
            r = [operator, operand]
        else:
            r = [operand, operator]
        return u"".join(r)

    symbol(id_).toPretty = toPretty
Ejemplo n.º 30
0
def prepostfix(id_):  # pre-/post-fix operators (++, --)
    def format(self, optns, state):
        r = self.commentsPretty(optns, state)
        operator = self.get("value")
        operand = self.getChild(0).format(optns, state)
        r += self.get("value")
        if self.get("left", '') == "true":
            r = [operator, operand]
        else:
            r = [operand, operator]
        return u''.join(r)

    symbol(id_).format = format
Ejemplo n.º 31
0
def preinfix(id_):  # pre-/infix operators (+, -)
    def toPretty(self, optns, state):  # need to handle pre/infix cases
        r = []
        first = self.getChild("first").toPretty(optns, state)
        op = self.get("value")
        prefix = self.get("left", 0)
        if prefix and prefix == "true":
            r = [op, first]
        else:
            second = self.getChild("second").toPretty(optns, state)
            r = [first, op, second]
        return ''.join(r)
    symbol(id_).toPretty = toPretty
Ejemplo n.º 32
0
def preinfix(id_):  # pre-/infix operators (+, -)
    def format(self, optns, state):  # need to handle pre/infix cases
        r = self.commentsPretty(self.comments, optns, state)
        r = [r]
        first = self.getChild(0).format(optns, state)
        op = self.get("value")
        prefix = self.get("left", 0)
        if prefix and prefix == "true":
            r = [op, first]
        else:
            second = self.getChild(1).format(optns, state)
            r = [first, ' ', op, ' ', second]
        return ''.join(r)
    symbol(id_).format = format
Ejemplo n.º 33
0
 def _visit_dyadic(self, node, operator):
     op1 = node.children[0]
     op2 = node.children[1]
     nnode = node
     if operator in self.operations:
         if operator in ['AND', 'OR'] and hasattr(op1, 'evaluated'): # short-circuit ops
             evaluated = self.operations[operator](op1.evaluated, op2)
             nnode = op1 if evaluated==op1.evaluated else op2
         elif all([hasattr(x, 'evaluated') for x in (op1, op2)]):
             evaluated = self.operations[operator](op1.evaluated, op2.evaluated)
             nnode = symbol("constant")(
                 node.get("line"), node.get("column"))
             set_node_type_from_value(nnode, evaluated)
             nnode.evaluated = evaluated
     return nnode
Ejemplo n.º 34
0
def preinfix(id_):  # pre-/infix operators (+, -)
    def format(self, optns, state):  # need to handle pre/infix cases
        r = self.commentsPretty(optns, state)
        r = [r]
        first = self.getChild(0).format(optns, state)
        op = self.get("value")
        prefix = self.get("left", 0)
        if prefix and prefix == "true":
            r = [op, first]
        else:
            second = self.getChild(1).format(optns, state)
            r = [first, ' ', op, ' ', second]
        return ''.join(r)

    symbol(id_).format = format
Ejemplo n.º 35
0
 def _visit_dyadic(self, node, operator):
     op1 = node.children[0]
     op2 = node.children[1]
     nnode = node
     if operator in self.operations:
         if operator in ['AND', 'OR'] and hasattr(
                 op1, 'evaluated'):  # short-circuit ops
             evaluated = self.operations[operator](op1.evaluated, op2)
             nnode = op1 if evaluated == op1.evaluated else op2
         elif all([hasattr(x, 'evaluated') for x in (op1, op2)]):
             evaluated = self.operations[operator](op1.evaluated,
                                                   op2.evaluated)
             if evaluated != ():
                 nnode = symbol("constant")(node.get("line"),
                                            node.get("column"))
                 set_node_type_from_value(nnode, evaluated)
                 nnode.evaluated = evaluated
     return nnode
Ejemplo n.º 36
0
 def _rewrite_if(self, if_node, cond_val):
     if cond_val:
         # use then branch
         replacement = if_node.children[1] 
         # rescue vardecl's from else branch, so these vars don't become global
         # if used elsewhere, but *don't* rescue their init's.
         if len(if_node.children) == 3:
             extracted_vars = extract_vars(if_node.children[2])
             add_vars(replacement, extracted_vars)
     else:
         # use else branch or empty
         if len(if_node.children) == 3:
             replacement = if_node.children[2]
         else:
             # don't leave single-statement parent loops empty (if_node.parent.type not in ("block", "file")
             replacement = treegenerator.symbol("block")(if_node.get("line"), if_node.get("column"))
         # rescue vardecl's from then branch
         extracted_vars = extract_vars(if_node.children[1])
         add_vars(replacement, extracted_vars)
     if_node.parent.replaceChild(if_node, replacement)
Ejemplo n.º 37
0
 def _rewrite_if(self, if_node, cond_val):
     if cond_val:
         # use then branch
         replacement = if_node.children[1]
         # rescue vardecl's from else branch, so these vars don't become global
         # if used elsewhere, but *don't* rescue their init's.
         if len(if_node.children) == 3:
             extracted_vars = extract_vars(if_node.children[2])
             add_vars(replacement, extracted_vars)
     else:
         # use else branch or empty
         if len(if_node.children) == 3:
             replacement = if_node.children[2]
         else:
             # don't leave single-statement parent loops empty (if_node.parent.type not in ("block", "file")
             replacement = treegenerator.symbol("block")(
                 if_node.get("line"), if_node.get("column"))
         # rescue vardecl's from then branch
         extracted_vars = extract_vars(if_node.children[1])
         add_vars(replacement, extracted_vars)
     if_node.parent.replaceChild(if_node, replacement)
Ejemplo n.º 38
0
def new_symbol(typ, enode):
    loc = enode['loc']['start']
    n = symbol(typ)(loc['line'], loc['column'] + 1)
    return n
Ejemplo n.º 39
0
def reduceOperation(literalNode):

    resultNode = None
    treeModified = False

    # can only reduce with constants
    if literalNode.type != "constant":
        return literalNode, False
    else:
        literalValue = constNodeToPyValue(literalNode)

    # check if we're in an operation
    ngParent = nextNongroupParent(literalNode)  # could be operand in ops
    if not ngParent or ngParent.type != "operation":
        return literalNode, False
    else:
        operationNode = ngParent
    # get operator
    operator = operationNode.get("operator")

    # normalize expression
    noperationNode = normalizeExpression(operationNode)
    # re-gain knownn literal node
    for node in treeutil.nodeIterator(noperationNode, [literalNode.type]):
        if literalNode.attributes == node.attributes:
            nliteralNode = node
            break

    # equal, unequal
    if operator in ["EQ", "SHEQ", "NE", "SHNE"]:
        otherOperand, _ = getOtherOperand(noperationNode, nliteralNode)
        if otherOperand.type != "constant":
            return literalNode, False
        if operator in ["EQ", "SHEQ"]:
            cmpFcn = operators.eq
        elif operator in ["NE", "SHNE"]:
            cmpFcn = operators.ne

        operands = [literalValue]
        otherVal = constNodeToPyValue(otherOperand)
        operands.append(otherVal)

        result = cmpFcn(operands[0], operands[1])
        resultNode = symbol("constant")(noperationNode.get("line"),
                                        noperationNode.get("column"))
        resultNode.set("constantType", "boolean")
        resultNode.set("value", str(result).lower())

    # order compares <, =<, ...
    elif operator in ["LT", "LE", "GT", "GE"]:
        otherOperand, otherPosition = getOtherOperand(noperationNode,
                                                      nliteralNode)
        if otherOperand.type != "constant":
            return literalNode, False
        if operator == "LT":
            cmpFcn = operators.lt
        elif operator == "LE":
            cmpFcn = operators.le
        elif operator == "GT":
            cmpFcn = operators.gt
        elif operator == "GE":
            cmpFcn = operators.ge

        operands = {}
        operands[1 - otherPosition] = literalValue
        otherVal = constNodeToPyValue(otherOperand)
        operands[otherPosition] = otherVal

        result = cmpFcn(operands[0], operands[1])
        resultNode = symbol("constant")(noperationNode.get("line"),
                                        noperationNode.get("column"))
        resultNode.set("constantType", "boolean")
        resultNode.set("value", str(result).lower())

    # logical ! (not)
    elif operator in ["NOT"]:
        result = not literalValue
        resultNode = symbol("constant")(noperationNode.get("line"),
                                        noperationNode.get("column"))
        resultNode.set("constantType", "boolean")
        resultNode.set("value", str(result).lower())

    # logical operators &&, ||
    elif operator in ["AND", "OR"]:
        result = None
        otherOperand, otherPosition = getOtherOperand(noperationNode,
                                                      nliteralNode)
        if operator == "AND":
            #if otherPosition==1 and not literalValue:  # short circuit
            #    result = False
            #else:
            cmpFcn = (lambda x, y: x and y)
        elif operator == "OR":
            #if otherPosition==1 and literalValue:  # short circuit
            #    result = True
            #else:
            cmpFcn = (lambda x, y: x or y)

        if result == None:
            if otherOperand.type != "constant":
                return literalNode, False
            operands = {}
            operands[1 - otherPosition] = literalValue
            otherVal = constNodeToPyValue(otherOperand)
            operands[otherPosition] = otherVal
            result = cmpFcn(operands[0], operands[1])
            resultNode = {
                literalValue: literalNode,
                otherVal: otherOperand
            }[result]

    # hook ?: operator
    elif operator in ["HOOK"]:
        if ngParent == noperationNode.children[
                0]:  # optimize a literal condition
            if bool(literalValue):
                resultNode = noperationNode.children[1]
            else:
                resultNode = noperationNode.children[2]

    # unsupported operation
    else:
        pass

    if resultNode != None:
        #print "optimizing: operation"
        operationNode.parent.replaceChild(operationNode, resultNode)
        treeModified = True
    else:
        resultNode = literalNode
        treeModified = False

    return resultNode, treeModified
Ejemplo n.º 40
0
        r = self.commentsPretty(optns, state)
        operator = self.get("value")
        operand = self.getChild("first").format(optns, state)
        r += self.get("value")
        if self.get("left", '') == "true":
            r = [operator, operand]
        else:
            r = [operand, operator]
        return u''.join(r)
    symbol(id_).format = format

for sym in SYMBOLS['prepostfix']:
    prepostfix(sym)


@method(symbol("constant"))
def format(self, optns, state):
    r = self.commentsPretty(optns, state)
    if self.get("constantType") == "string":
        if self.get("detail") == "singlequotes":
            r += self.write("'")
        else:
            r += self.write('"')
        r += self.write(self.get("value"))
        if self.get("detail") == "singlequotes":
            r += self.write("'")
        else:
            r += self.write('"')
    else:
        r += self.write(self.get("value"))
    return r
Ejemplo n.º 41
0
def reduceOperation(literalNode): 

    resultNode = None
    treeModified = False

    # can only reduce with constants
    if literalNode.type != "constant":
        return literalNode, False
    else:
        literalValue = constNodeToPyValue(literalNode)

    # check if we're in an operation
    ngParent = nextNongroupParent(literalNode) # could be operand in ops
    if not ngParent or ngParent.type != "operation":
        return literalNode, False
    else:
        operationNode = ngParent
    # get operator
    operator = operationNode.get("operator")

    # normalize expression
    noperationNode = normalizeExpression(operationNode)
    # re-gain knownn literal node
    for node in treeutil.nodeIterator(noperationNode, [literalNode.type]):
        if literalNode.attributes == node.attributes:
            nliteralNode = node
            break

    # equal, unequal
    if operator in ["EQ", "SHEQ", "NE", "SHNE"]:
        otherOperand, _ = getOtherOperand(noperationNode, nliteralNode)
        if otherOperand.type != "constant":
            return literalNode, False
        if operator in ["EQ", "SHEQ"]:
            cmpFcn = operators.eq
        elif operator in ["NE", "SHNE"]:
            cmpFcn = operators.ne

        operands = [literalValue]
        otherVal = constNodeToPyValue(otherOperand)
        operands.append(otherVal)
         
        result = cmpFcn(operands[0],operands[1])
        resultNode = symbol("constant")(
            noperationNode.get("line"), noperationNode.get("column"))
        resultNode.set("constantType","boolean")
        resultNode.set("value", str(result).lower())

    # order compares <, =<, ...
    elif operator in ["LT", "LE", "GT", "GE"]:
        otherOperand, otherPosition = getOtherOperand(noperationNode, nliteralNode)
        if otherOperand.type != "constant":
            return literalNode, False
        if operator == "LT":
            cmpFcn = operators.lt
        elif operator == "LE":
            cmpFcn = operators.le
        elif operator == "GT":
            cmpFcn = operators.gt
        elif operator == "GE":
            cmpFcn = operators.ge

        operands = {}
        operands[1 - otherPosition] = literalValue
        otherVal = constNodeToPyValue(otherOperand)
        operands[otherPosition] = otherVal

        result = cmpFcn(operands[0], operands[1])
        resultNode = symbol("constant")(
            noperationNode.get("line"), noperationNode.get("column"))
        resultNode.set("constantType","boolean")
        resultNode.set("value", str(result).lower())

    # logical ! (not)
    elif operator in ["NOT"]:
        result = not literalValue
        resultNode = symbol("constant")(
            noperationNode.get("line"), noperationNode.get("column"))
        resultNode.set("constantType","boolean")
        resultNode.set("value", str(result).lower())

    # logical operators &&, ||
    elif operator in ["AND", "OR"]:
        result = None
        otherOperand, otherPosition = getOtherOperand(noperationNode, nliteralNode)
        if operator == "AND":
            #if otherPosition==1 and not literalValue:  # short circuit
            #    result = False
            #else:
            cmpFcn = (lambda x,y: x and y)
        elif operator == "OR":
            #if otherPosition==1 and literalValue:  # short circuit
            #    result = True
            #else:
            cmpFcn = (lambda x,y: x or y)

        if result == None:
            if otherOperand.type != "constant":
                return literalNode, False
            operands = {}
            operands[1 - otherPosition] = literalValue
            otherVal = constNodeToPyValue(otherOperand)
            operands[otherPosition] = otherVal
            result = cmpFcn(operands[0], operands[1])
            resultNode = {literalValue:literalNode, otherVal:otherOperand}[result]

    # hook ?: operator
    elif operator in ["HOOK"]:
        if ngParent == noperationNode.children[0]: # optimize a literal condition
            if bool(literalValue):
                resultNode = noperationNode.children[1]
            else:
                resultNode = noperationNode.children[2]

    # unsupported operation
    else:
        pass

    if resultNode != None:
        #print "optimizing: operation"
        operationNode.parent.replaceChild(operationNode, resultNode)
        treeModified = True
    else:
        resultNode = literalNode
        treeModified = False

    return resultNode, treeModified
Ejemplo n.º 42
0
def inlineIfStatement(ifNode, conditionValue):
    """
    Inline an if statement assuming that the condition of the if
    statement evaluates to "conditionValue" (True/False")
    """

    if ifNode.type != "loop" or ifNode.get("loopType") != "IF":
        raise tree.NodeAccessException("Expected the LOOP node of an if statement!", mapNode)

    replacement = []
    newDefinitions = []
    removedDefinitions = []

    if len(ifNode.children)==3:  # there is an 'else' part
        if conditionValue:
            removedDefinitions = getDefinitions(ifNode.children[2])
            newDefinitions = getDefinitions(ifNode.children[1])
            replacement = ifNode.children[1].children[0]  # <body>.children: single node, <block> or <statement>
        else:
            removedDefinitions = getDefinitions(ifNode.children[1])
            newDefinitions = getDefinitions(ifNode.children[2])
            replacement = ifNode.children[2].children[0]
    else:
        if conditionValue:
            newDefinitions = getDefinitions(ifNode.children[1])
            replacement = ifNode.children[1].children[0]
        else:
            removedDefinitions = getDefinitions(ifNode.children[1])

    newDefinitions = [x.getDefinee().get("value") for x in newDefinitions]
    definitions = []
    for definition in removedDefinitions:
        if not definition.getDefinee().get("value") in newDefinitions:
            definitions.append(definition)

    if len(definitions) > 0:
        defList = treegenerator.symbol("var")()
        defList.set("line", ifNode.get("line"))
        defList.set("column", ifNode.get("column"))
        for definition in definitions:
            # remove initialisations
            if definition.children[0].type == "identifier":
                pass
            else: # assignment
                idf = definition.getDefinee()
                definition.children[0] = idf
            defList.addChild(definition)

        # move defList to higher node
        node = ifNode
        while node.type not in ("statements",):
            if node.parent:
                node = node.parent
            else:
                break
        node.addChild(defList,0)

    # move replacement
    if replacement:
        replaceChildWithNodes(ifNode.parent, ifNode, [replacement]) # helper expects list
    else:
        emptyBlock = treegenerator.symbol("block")()
        emptyBlock.set("line", ifNode.get("line"))
        # TODO: experimental bug#4734: is this enough?
        if (ifNode.parent.type in ["block", "file"]):
            ifNode.parent.removeChild(ifNode)
        else:
            # don't leave single-statement parent loops empty
            ifNode.parent.replaceChild(ifNode, emptyBlock)
        replacement = emptyBlock

    return replacement
Ejemplo n.º 43
0
        operand = self.getChild("first").toPretty(optns, state)
        r += self.get("value")
        if self.get("left", '') == "true":
            r = [operator, operand]
        else:
            r = [operand, operator]
        return u''.join(r)

    symbol(id_).toPretty = toPretty


for sym in SYMBOLS['prepostfix']:
    prepostfix(sym)


@method(symbol("constant"))
def toPretty(self, optns, state):
    r = self.commentsPretty(optns, state)
    if self.get("constantType") == "string":
        if self.get("detail") == "singlequotes":
            r += self.write("'")
        else:
            r += self.write('"')
        r += self.write(self.get("value"))
        if self.get("detail") == "singlequotes":
            r += self.write("'")
        else:
            r += self.write('"')
    else:
        r += self.write(self.get("value"))
    return r
Ejemplo n.º 44
0
 def visit_EmptyStatement(self, enode):
     return symbol('(empty)')()
Ejemplo n.º 45
0
def new_symbol(typ, enode):
    loc = enode['loc']['start']
    n = symbol(typ)(loc['line'], loc['column']+1)
    return n
Ejemplo n.º 46
0
 def visit_EmptyStatement(self, enode):
     return symbol('(empty)')()
Ejemplo n.º 47
0
def inlineIfStatement(ifNode, conditionValue):
    """
    Inline an if statement assuming that the condition of the if
    statement evaluates to "conditionValue" (True/False")
    """

    if ifNode.type != "loop" or ifNode.get("loopType") != "IF":
        raise tree.NodeAccessException("Expected the LOOP node of an if statement!", mapNode)

    replacement = []
    newDefinitions = []
    removedDefinitions = []

    if len(ifNode.children)==3:  # there is an 'else' part
        if conditionValue:
            removedDefinitions = getDefinitions(ifNode.children[2])
            newDefinitions = getDefinitions(ifNode.children[1])
            replacement = ifNode.children[1].children[0].children
        else:
            removedDefinitions = getDefinitions(ifNode.children[1])
            newDefinitions = getDefinitions(ifNode.children[2])
            replacement = ifNode.children[2].children[0].children
    else:
        if conditionValue:
            newDefinitions = getDefinitions(ifNode.children[1])
            replacement = ifNode.children[1].children[0].children
        else:
            removedDefinitions = getDefinitions(ifNode.children[1])

    newDefinitions = [x.getDefinee().get("value") for x in newDefinitions]
    definitions = []
    for definition in removedDefinitions:
        if not definition.getDefinee().get("value") in newDefinitions:
            definitions.append(definition)

    if len(definitions) > 0:
        defList = treegenerator.symbol("var")()
        defList.set("line", ifNode.get("line"))
        defList.set("column", ifNode.get("column"))
        for definition in definitions:
            # remove initialisations
            if definition.children[0].type == "identifier":
                pass
            else: # assignment
                idf = definition.getDefinee()
                definition.children[0] = idf
            defList.addChild(definition)

        # move defList to higher node
        node = ifNode
        while node.type not in ("statements",):
            if node.parent:
                node = node.parent
            else:
                break
        node.addChild(defList,0)

    # move replacement
    if replacement:
        replacement = replacement[:] # retain copy for return value
        replaceChildWithNodes(ifNode.parent, ifNode, replacement)
    else:
        emptyBlock = treegenerator.symbol("block")()
        emptyBlock.set("line", ifNode.get("line"))
        # TODO: experimental bug#4734: is this enough?
        if (ifNode.parent.type in ["block", "file"]):
            ifNode.parent.removeChild(ifNode)
        else:
            # don't leave single-statement parent loops empty
            ifNode.parent.replaceChild(ifNode, emptyBlock)
        replacement = [emptyBlock]

    return replacement
Ejemplo n.º 48
0
def inlineIfStatement(ifNode, conditionValue, inPlace=True):
    """
    Inline an if statement assuming that the condition of the if
    statement evaluates to "conditionValue" (True/False")
    """

    if ifNode.type != "loop" or ifNode.get("loopType") != "IF":
        raise tree.NodeAccessException(
            "Expected the LOOP node of an if statement!", ifNode)

    replacement = None
    replacement_is_empty = False
    newDefinitions = []
    removedDefinitions = []

    if len(ifNode.children) == 3:  # there is an 'else' part
        if conditionValue:
            removedDefinitions = getDefinitions(ifNode.children[2])
            newDefinitions = getDefinitions(ifNode.children[1])
            replacement = ifNode.children[1].children[
                0]  # <body>.children: single node, <block> or <statement>
        else:
            removedDefinitions = getDefinitions(ifNode.children[1])
            newDefinitions = getDefinitions(ifNode.children[2])
            replacement = ifNode.children[2].children[0]
    else:
        if conditionValue:
            newDefinitions = getDefinitions(ifNode.children[1])
            replacement = ifNode.children[1].children[0]
        else:
            removedDefinitions = getDefinitions(ifNode.children[1])
            # don't leave single-statement parent loops empty
            emptyBlock = treegenerator.symbol("block")()
            emptyBlock.set("line", ifNode.get("line"))
            stmts = treegenerator.symbol("statements")()
            stmts.set("line", ifNode.get("line"))
            emptyBlock.addChild(stmts)
            replacement = emptyBlock
            replacement_is_empty = True

    # Rescue var decls
    newDefinitions = [x.getDefinee().get("value") for x in newDefinitions]
    definitions = []
    for definition in removedDefinitions:
        if not definition.getDefinee().get("value") in newDefinitions:
            definitions.append(definition)

    if len(definitions) > 0:
        defList = treegenerator.symbol("var")()
        defList.set("line", ifNode.get("line"))
        defList.set("column", ifNode.get("column"))
        for definition in definitions:
            # remove initialisations
            if definition.children[0].type == "identifier":
                pass
            else:  # assignment
                idf = definition.getDefinee()
                definition.children[0] = idf
            defList.addChild(definition)

        # attach defList to replacement
        if replacement.type != 'block':  # treat single-statement branches
            block = treegenerator.symbol("block")()
            block.set("line", ifNode.get("line"))
            stmts = treegenerator.symbol("statements")()
            stmts.set("line", ifNode.get("line"))
            block.addChild(stmts)
            stmts.addChild(replacement)
            replacement = block
        replacement.getChild("statements").addChild(defList, 0)
        replacement_is_empty = False

    # move replacement
    if inPlace:
        if (replacement_is_empty and ifNode.parent.type in ["statements"]):
            ifNode.parent.removeChild(ifNode)
        else:
            ifNode.parent.replaceChild(ifNode, replacement)

    return replacement, replacement_is_empty
Ejemplo n.º 49
0
def inlineIfStatement(ifNode, conditionValue, inPlace=True):
    """
    Inline an if statement assuming that the condition of the if
    statement evaluates to "conditionValue" (True/False")
    """

    if ifNode.type != "loop" or ifNode.get("loopType") != "IF":
        raise tree.NodeAccessException("Expected the LOOP node of an if statement!", ifNode)

    replacement = None
    replacement_is_empty = False
    newDefinitions = []
    removedDefinitions = []

    if len(ifNode.children)==3:  # there is an 'else' part
        if conditionValue:
            removedDefinitions = getDefinitions(ifNode.children[2])
            newDefinitions = getDefinitions(ifNode.children[1])
            replacement = ifNode.children[1].children[0]  # <body>.children: single node, <block> or <statement>
        else:
            removedDefinitions = getDefinitions(ifNode.children[1])
            newDefinitions = getDefinitions(ifNode.children[2])
            replacement = ifNode.children[2].children[0]
    else:
        if conditionValue:
            newDefinitions = getDefinitions(ifNode.children[1])
            replacement = ifNode.children[1].children[0]
        else:
            removedDefinitions = getDefinitions(ifNode.children[1])
            # don't leave single-statement parent loops empty
            emptyBlock = treegenerator.symbol("block")()
            emptyBlock.set("line", ifNode.get("line"))
            stmts = treegenerator.symbol("statements")()
            stmts.set("line", ifNode.get("line"))
            emptyBlock.addChild(stmts)
            replacement = emptyBlock
            replacement_is_empty = True

    # Rescue var decls
    newDefinitions = [x.getDefinee().get("value") for x in newDefinitions]
    definitions = []
    for definition in removedDefinitions:
        if not definition.getDefinee().get("value") in newDefinitions:
            definitions.append(definition)

    if len(definitions) > 0:
        defList = treegenerator.symbol("var")()
        defList.set("line", ifNode.get("line"))
        defList.set("column", ifNode.get("column"))
        for definition in definitions:
            # remove initialisations
            if definition.children[0].type == "identifier":
                pass
            else: # assignment
                idf = definition.getDefinee()
                definition.children[0] = idf
            defList.addChild(definition)

        # attach defList to replacement
        if replacement.type != 'block': # treat single-statement branches
            block = treegenerator.symbol("block")()
            block.set("line", ifNode.get("line"))
            stmts = treegenerator.symbol("statements")()
            stmts.set("line", ifNode.get("line"))
            block.addChild(stmts)
            stmts.addChild(replacement)
            replacement = block
        replacement.getChild("statements").addChild(defList,0)
        replacement_is_empty = False

    # move replacement
    if inPlace:
        if (replacement_is_empty and ifNode.parent.type in ["statements"]):
            ifNode.parent.removeChild(ifNode)
        else:
            ifNode.parent.replaceChild(ifNode, replacement)

    return replacement, replacement_is_empty
Ejemplo n.º 50
0
class Formatter(treeutil.NodeVisitor):
    def __init__(self, root_node, options, state):
        super(Formatter, self).__init__()
        self.root_node = root_node
        self.optns = options
        self.state = state

    def visit(self, node):
        r = []
        r += [self.commentsPretty(node.comments)]
        if hasattr(self, "visit_" + node.type):
            if self.debug: print "visiting:", node.type
            getattr(self, "visit_" + node.type)(node)
        elif node.children:
            for child in node.children:
                r.append(self.visit(child))
        else:
            r += [self.get("value", u'')]
        r += [self.commentsPretty(node.commentsAfter)]
        return u''.join(r)

    def commentsPretty(self, comments):
        res = []
        for i, commentNode in enumerate(comments):
            commentStr = self.visit(commentNode)
            res.append(commentStr)
            # handle additional line breaks between comments
            if i > 0:
                pass
                #curr_start = commentNode.get("line")
                #prev_start = comments[i-1].get("line")
                #prev_lines = res[i-1].count('\n')
                #addtl_lb = curr_start - prev_start + prev_lines
                #res[i-1] += addtl_lb * '\n'
        return u''.join(res)

    def infix(id_):
        def visit_(self, optns, state):
            r = self.commentsPretty(self.comments, optns, state)
            r += self.getChild(0).format(optns, state)
            r += ' '
            r += self.get("value")
            r += ' '
            r += self.getChild(1).format(optns, state)
            return r

        symbol(id_).format = format

    for sym in SYMBOLS['infix'] + SYMBOLS['infix_r']:
        infix(sym)

    ##
    # infix "verb" operators, i.e. that need a space around themselves (like 'instanceof', 'in')
    def infix_v(id_):
        def visit_(self, optns, state):  # adapt the output
            r = self.commentsPretty(self.comments, optns, state)
            r += self.getChild(0).format(optns, state)
            r += self.space()
            r += self.get("value")
            r += self.space()
            r += self.getChild(1).format(optns, state)
            return r

        symbol(id_).format = format

    for sym in SYMBOLS['infix_v']:
        infix_v(sym)

    ##
    # prefix "sigil" operators, like '!', '~', ...
    def prefix(id_):
        def visit_(self, optns, state):
            r = self.commentsPretty(self.comments, optns, state)
            r += self.get("value")
            r += self.getChild(0).format(optns, state)
            return r

        symbol(id_).format = format

    for sym in SYMBOLS['prefix']:
        prefix(sym)

    ##
    # prefix "verb" operators, i.e. that need a space before their operand like 'delete'
    def prefix_v(id_):
        def visit_(self, optns, state):
            r = self.commentsPretty(self.comments, optns, state)
            r += self.get("value")
            r += self.space()
            r += self.getChild(0).format(optns, state)
            return r

        symbol(id_).format = format

    for sym in SYMBOLS['prefix_v']:
        prefix_v(sym)

    def preinfix(id_):  # pre-/infix operators (+, -)
        def visit_(self, optns, state):  # need to handle pre/infix cases
            r = self.commentsPretty(self.comments, optns, state)
            r = [r]
            first = self.getChild(0).format(optns, state)
            op = self.get("value")
            prefix = self.get("left", 0)
            if prefix and prefix == "true":
                r = [op, first]
            else:
                second = self.getChild(1).format(optns, state)
                r = [first, ' ', op, ' ', second]
            return ''.join(r)

        symbol(id_).format = format

    for sym in SYMBOLS['preinfix']:
        preinfix(sym)

    def prepostfix(id_):  # pre-/post-fix operators (++, --)
        def visit_(self, optns, state):
            r = self.commentsPretty(self.comments, optns, state)
            operator = self.get("value")
            operand = self.getChild(0).format(optns, state)
            r += self.get("value")
            if self.get("left", '') == "true":
                r = [operator, operand]
            else:
                r = [operand, operator]
            return u''.join(r)

        symbol(id_).format = format

    for sym in SYMBOLS['prepostfix']:
        prepostfix(sym)

    def visit_constant(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        if self.get("constantType") == "string":
            if self.get("detail") == "singlequotes":
                r += self.write("'")
            else:
                r += self.write('"')
            r += self.write(self.get("value"))
            if self.get("detail") == "singlequotes":
                r += self.write("'")
            else:
                r += self.write('"')
        else:
            r += self.write(self.get("value"))
        return r

    def visit_identifier(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        v = self.get("value", u"")
        if v:
            r += self.write(v)
        return r

    def visit_hook(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r = [r]
        r.append(self.getChild(0).format(optns, state))
        r.append(' ')
        r.append('?')
        r.append(' ')
        r.append(self.getChild(1).format(optns, state))
        r.append(' ')
        r.append(':')
        r.append(' ')
        r.append(self.getChild(2).format(optns, state))
        return ''.join(r)

    def visit_dotaccessor(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r += self.children[0].format(optns, state)
        r += '.'
        r += self.children[1].format(optns, state)
        return r

    def visit_operand(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r += self.children[0].format(optns, state)
        return r

    def visit_group(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r = [r]
        r.append('(')
        a = []
        for c in self.children:
            a.append(c.format(optns, state))
        r.append(', '.join(a))
        r.append(')')
        return ''.join(r)

    def visit_accessor(self, optns, state):
        r = self.children[0].format(optns, state)
        r += self.commentsPretty(self.comments, optns, state)
        r += '['
        r += self.children[1].format(optns, state)
        r += ']'
        return r

    def visit_array(self, optns, state):
        cmnts = self.commentsPretty(self.comments, optns, state)
        r = []
        for c in self.children:
            r.append(c.format(optns, state))
        return cmnts + '[' + u', '.join(r) + ']'

    def visit_key(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r += self.children[0].format(optns, state)
        r += self.commentsPretty(self.commentsAfter, optns, state)
        return r

    def visit_map(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r += self.write("{\n")
        state.indentLevel += 1
        indent = indentString(optns, state)
        a = []
        for c in self.children:
            a.append(indent + c.format(optns, state))
        r += (',\n').join(a)
        state.indentLevel -= 1
        if len(self.children):
            r += '\n'
        r += self.write("%s}" % indentString(optns, state))
        return r

    def visit_value(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r += self.children[0].format(optns, state)
        return r

    def visit_keyvalue(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        key = self.get("key")
        key_quote = self.get("quote", '')
        if key_quote:
            quote = '"' if key_quote == 'doublequotes' else "'"
        elif (key in lang.RESERVED or not identifier_regex.match(key)
              # TODO: or not lang.NUMBER_REGEXP.match(key)
              ):
            print "Warning: Auto protect key: %r" % key
            quote = '"'
        else:
            quote = ''
        value = self.getChild("value").format(optns, state)
        return r + quote + key + quote + ' : ' + value

    def visit_block(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r = [r]
        r.append('{')
        r.append(self.children[0].format(optns, state))
        r.append('}')
        return u''.join(r)

    def visit_function(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r += self.write("function")
        if self.getChild("identifier", 0):
            functionName = self.getChild("identifier").get("value")
            r += self.space(result=r)
            r += self.write(functionName)
        # params
        r += self.getChild("params").format(optns, state)
        # body
        r += self.getChild("body").format(optns, state)
        return r

    def visit_body(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r = [r]
        r.append(self.children[0].format(optns, state))
        # 'if', 'while', etc. can have single-statement bodies
        if self.children[0].id != 'block':
            r.append(';')
        return u''.join(r)

    def visit_var(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r = [r]
        r.append("var")
        r.append(self.space())
        a = []
        for c in self.children:
            a.append(c.format(optns, state))
        r.append(','.join(a))
        return ''.join(r)

    def visit_definition(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r += self.children[0].format(optns, state)
        return r

    def visit_for(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r = [r]
        r.append('for')
        r.append(self.space(False, result=r))
        # cond
        r.append('(')
        # for (in)
        if self.get("forVariant") == "in":
            r.append(self.children[0].format(optns, state))
        # for (;;)
        else:
            r.append(self.children[0].children[0].format(optns, state))
            r.append(';')
            r.append(self.children[0].children[1].format(optns, state))
            r.append(';')
            r.append(self.children[0].children[2].format(optns, state))
        r.append(')')
        # body
        r.append(self.getChild("body").format(optns, state))
        return u''.join(r)

    def visit_in(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r += self.getChild(0).format(optns, state)
        r += self.space()
        r += 'in'
        r += self.space()
        r += self.getChild(1).format(optns, state)
        return r

    def visit_expressionList(
            self, optns, state
    ):  # WARN: this conflicts (and is overwritten) in for(;;).format
        cmnts = self.commentsPretty(self.comments, optns, state)
        r = []
        for c in self.children:
            r.append(c.format(optns, state))
        return cmnts + ','.join(r)

    def visit_while(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r += self.write("while")
        r += self.space(False, result=r)
        # cond
        r += '('
        r += self.children[0].format(optns, state)
        r += ')'
        # body
        r += self.children[1].format(optns, state)
        return r

    def visit_with(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r = [r]
        r.append("with")
        r.append(self.space())
        r.append('(')
        r.append(self.children[0].format(optns, state))
        r.append(')')
        r.append(self.children[1].format(optns, state))
        return ''.join(r)

    def visit_do(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r = [r]
        r.append("do")
        r.append(self.space())
        r.append(self.children[0].format(optns, state))
        r.append('while')
        r.append('(')
        r.append(self.children[1].format(optns, state))
        r.append(')')
        return ''.join(r)

    def visit_if(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        # Additional new line before each loop
        if not self.isFirstChild(True) and not self.getChild(
                "commentsBefore", False):
            prev = self.getPreviousSibling(False, True)

            # No separation after case statements
            #if prev != None and prev.type in ["case", "default"]:
            #    pass
            #elif self.hasChild("elseStatement") or self.getChild("statement").hasBlockChildren():
            #    self.sep()
            #else:
            #    self.line()
        r += self.write("if")
        # condition
        r += self.write("(")
        r += self.children[0].format(optns, state)
        r += self.write(")")
        # 'then' part
        r += self.children[1].format(optns, state)
        # (opt) 'else' part
        if len(self.children) == 3:
            r += self.space()
            r += self.write("else")
            r += self.space()
            r += self.children[2].format(optns, state)
        r += self.space(False, result=r)
        return r

    def visit_loop(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        # Additional new line before each loop
        if not self.isFirstChild(True) and not self.getChild(
                "commentsBefore", False):
            prev = self.getPreviousSibling(False, True)

            # No separation after case statements
            if prev != None and prev.type in ["case", "default"]:
                pass
            elif self.hasChild("elseStatement") or self.getChild(
                    "statement").hasBlockChildren():
                self.sep()
            else:
                self.line()

        loopType = self.get("loopType")

        if loopType == "IF":
            pass
        #    r += self.write("if")
        #    r += self.space(False,result=r)
        #    # condition
        #    r += '('
        #    r += self.children[0].format(optns, state)
        #    r += ')'
        #    # then
        #    r += self.children[1].format(optns, state)
        #    # else
        #    if len(self.children) == 3:
        #        r += self.write("else")
        #        r += self.children[2].format(optns, state)
        #    r += self.space(False,result=r)

        elif loopType == "WHILE":
            r += self.write("while")
            r += self.space(False, result=r)

        elif loopType == "FOR":
            r += self.write("for")
            r += self.space(False, result=r)

        elif loopType == "DO":
            r += self.write("do")
            r += self.space(False, result=r)

        elif loopType == "WITH":
            r += self.write("with")
            r += self.space(False, result=r)

        else:
            print "Warning: Unknown loop type: %s" % loopType
        return r

    def visit_break(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r += self.write("break")
        if self.children:
            r += self.space(result=r)
            r += self.write(self.children[0].format(optns, state))
        return r

    def visit_continue(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r += self.write("continue")
        if self.children:
            r += self.space(result=r)
            r += self.write(self.children[0].format(optns, state))
        return r

    def visit_return(self, optns, state):
        r = [self.commentsPretty(self.comments, optns, state)]
        r += ["return"]
        if self.children:
            r.append(self.space())
            r.append(self.children[0].format(optns, state))
        return ''.join(r)

    def visit_switch(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r = [r]
        r.append("switch")
        # control
        r.append('(')
        r.append(self.children[0].format(optns, state))
        r.append(')')
        # body
        r.append('{')
        body = self.getChild("body")
        for c in body.children:
            r.append(c.format(optns, state))
        r.append('}')
        return ''.join(r)

    def visit_case(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r = [r]
        r.append('case')
        r.append(self.space())
        r.append(self.children[0].format(optns, state))
        r.append(':')
        if len(self.children) > 1:
            r.append(self.children[1].format(optns, state))
        return ''.join(r)

    def visit_default(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r = [r]
        r.append('default')
        r.append(':')
        if len(self.children) > 0:
            r.append(self.children[0].format(optns, state))
        return ''.join(r)

    def visit_try(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r = [r]
        r.append("try")
        r.append(self.children[0].format(optns, state))
        catch = self.getChild("catch", 0)
        if catch:
            r.append(self.space())
            r.append("catch")
            r.append(catch.children[0].format(optns, state))
            r.append(self.space())
            r.append(catch.children[1].format(optns, state))
        finally_ = self.getChild("finally", 0)
        if finally_:
            r.append("finally")
            r.append(finally_.children[0].format(optns, state))
        return ''.join(r)

    def visit_throw(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r += 'throw'
        r += self.space()
        r += self.children[0].format(optns, state)
        return r

    def visit_empty(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        return r

    def visit_label(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r = [r]
        r += [self.get("value")]  # identifier
        r += [":"]
        r += [self.children[0].format(optns, state)]
        return ''.join(r)

    def visit_statements(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r = [r]
        indent = indentString(optns, state)
        for cld in self.children:
            l = [indent]
            c = cld.format(optns, state)
            l.append(c)
            if not c or c[-1] != ';':
                l.append(';')
            r.append(u''.join(l))
        return u'\n'.join(r)

    def visit_block(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r += self.write("{\n")
        state.indentLevel += 1
        a = []
        for c in self.children:  # should be just "statements"
            a.append(c.format(optns, state))
        a_ = u''.join(a)
        r += a_
        if a_:
            r += "\n"
        state.indentLevel -= 1
        indent_string = indentString(optns, state)
        r += self.write(indent_string + "}")
        return r

    def visit_call(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r += self.getChild("operand").format(optns, state)
        r += self.getChild("arguments").format(optns, state)
        return r

    def visit_comment(self, optns, state):
        r = self.get("value")
        r = Comment.Text(r).indent(indentString(optns, state))
        if self.get(
                'end',
                False) == True:  # 'inline' needs terminating newline anyway
            r += '\n'
        r += indentString(
            optns, state
        )  # to pass on the indentation that was set ahead of the comment
        return r

    def visit_commentsAfter(self, optns, state):
        r = self.toJS(pp)
        return r

    def visit_commentsBefore(self, optns, state):
        r = self.toJS(pp)
        return r

    def visit_file(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        r += self.children[0].format(optns, state)
        return r

    def visit_first(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        if self.children:  # could be empty in for(;;)
            r = self.children[0].format(optns, state)
        return r

    def visit_second(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        if self.children:
            r = self.children[0].format(optns, state)
        return r

    def visit_third(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        if self.children:
            r += self.children[0].format(optns, state)
        return r

    def visit_(self, optns, state):
        r = self.commentsPretty(self.comments, optns, state)
        self.noline()
        r += self.write("(")
        a = []
        for c in self.children:
            a.append(c.format(optns, state))
        r += u', '.join(a)
        r += self.write(")")
        return r

    symbol("params").format = format
    symbol("arguments").format = format