code: def negate(node):
      if isinstance(node, ast.Name):
          # Not type info, could be anything :(
          raise UnsupportedExpression()
  
      if isinstance(node, ast.UnaryOp):
          # !~x <> ~x == 0 <> x == ~0 <> x == -1
          if isinstance(node.op, ast.Invert):
              return ast.Compare(
                  node.operand, [ast.Eq()], [ast.Constant(-1, None)]
              )
          # !!x <> x
          if isinstance(node.op, ast.Not):
              return node.operand
          # !+x <> +x == 0 <> x == 0 <> !x
          if isinstance(node.op, ast.UAdd):
              return node.operand
          # !-x <> -x == 0 <> x == 0 <> !x
          if isinstance(node.op, ast.USub):
              return node.operand
  
      if isinstance(node, ast.BoolOp):
          new_values = [ast.UnaryOp(ast.Not(), v) for v in node.values]
          # !(x or y) <> !x and !y
          if isinstance(node.op, ast.Or):
              return ast.BoolOp(ast.And(), new_values)
          # !(x and y) <> !x or !y
          if isinstance(node.op, ast.And):
              return ast.BoolOp(ast.Or(), new_values)
  
      if isinstance(node, ast.Compare):
          cmps = [
              ast.Compare(x, [negate(o)], [y])
              for x, o, y in zip(
                  [node.left] + node.comparators[:-1],
                  node.ops,
                  node.comparators,
              )
          ]
          if len(cmps) == 1:
              return cmps[0]
          return ast.BoolOp(ast.Or(), cmps)
  
      if isinstance(node, ast.Eq):
          return ast.NotEq()
      if isinstance(node, ast.NotEq):
          return ast.Eq()
      if isinstance(node, ast.Gt):
          return ast.LtE()
      if isinstance(node, ast.GtE):
          return ast.Lt()
      if isinstance(node, ast.Lt):
          return ast.GtE()
      if isinstance(node, ast.LtE):
          return ast.Gt()
      if isinstance(node, ast.In):
          return ast.NotIn()
      if isinstance(node, ast.NotIn):
          return ast.In()
  
      if isinstance(node, ast.Attribute):
          if node.attr == "False":
              return ast.Constant(True, None)
          if node.attr == "True":
              return ast.Constant(False, None)
  
      raise UnsupportedExpression()
  
imports: import gast
  from collections import defaultdict
  from functools import reduce
  from pythran.analyses import Aliases, CFG
  from pythran.intrinsic import Intrinsic
  from pythran.passmanager import ModuleAnalysis
  from pythran.interval import Interval, IntervalTuple, UNKNOWN_RANGE
  from pythran.tables import MODULES, attributes
label_desc: Use image node_id 2 for calling a global function with example usage: negate(node) and returns: ast, ast, ast, ast, ast, ast, ast, ast, ast, ast, node, node, node, ast, ast, cmps, ast, ast