Handle assignment nodes

        :node: TODO
        :scope: TODO
        :ctxt: TODO
        :stream: TODO
        :returns: TODO
978717
def _handle_assignment(self, node, scope, ctxt, stream):
        
        def add_op(x,y): x += y
        def sub_op(x,y): x -= y
        def div_op(x,y): x /= y
        def mod_op(x,y): x %= y
        def mul_op(x,y): x *= y
        def xor_op(x,y): x ^= y
        def and_op(x,y): x &= y
        def or_op(x,y): x |= y
        def lshift_op(x,y): x <<= y
        def rshift_op(x,y): x >>= y
        def assign_op(x,y): x._pfp__set_value(y)

        switch = {
            "+="    : add_op,
            "-="    : sub_op,
            "/="    : div_op,
            "%="    : mod_op,
            "*="    : mul_op,
            "^="    : xor_op,
            "&="    : and_op,
            "|="    : or_op,
            "<<="    : lshift_op,
            ">>="    : rshift_op,
            "="        : assign_op
        }

        self._dlog("handling assignment")
        field = self._handle_node(node.lvalue, scope, ctxt, stream)
        self._dlog("field = {}".format(field))
        value = self._handle_node(node.rvalue, scope, ctxt, stream)

        if node.op is None:
            self._dlog("value = {}".format(value))
            field._pfp__set_value(value)
        else:
            self._dlog("value {}= {}".format(node.op, value))
            if node.op not in switch:
                raise errors.UnsupportedAssignmentOperator(node.coord, node.op)
            switch[node.op](field, value)
452411
def _handle_union(self, node, scope, ctxt, stream):
        
        self._dlog("handling union")

        union_cls = StructUnionDef("union", self, node)
        return union_cls
920517
function onEnter(assignment) {
  // TODO: GCLI doesn't support passing a context to notifications of cursor
  // position, so onEnter/onLeave/onChange are disabled below until we fix this
  assignment.highlighter = new Highlighter(context.environment.window.document);
  assignment.highlighter.nodelist = assignment.conversion.matches;
}
417830
function AssignmentPattern(node, print) {
  print.plain(node.left);
  this.push(" = ");
  print.plain(node.right);
}
326412
def _handle_constant(self, node, scope, ctxt, stream):
        
        self._dlog("handling constant type {}".format(node.type))
        switch = {
            "int": (self._str_to_int, self._choose_const_int_class),
            "long": (self._str_to_int, self._choose_const_int_class),
            # TODO this isn't quite right, but py010parser wouldn't have
            # parsed it if it wasn't correct...
            "float": (lambda x: float(x.lower().replace("f", "")), fields.Float),
            "double": (float, fields.Double),

            # cut out the quotes
            "char": (lambda x: ord(utils.string_escape(x[1:-1])), fields.Char),

            # TODO should this be unicode?? will probably bite me later...
            # cut out the quotes
            "string": (lambda x: str(utils.string_escape(x[1:-1])), fields.String)
        }

        if node.type in switch:
            #return switch[node.type](node.value)
            conversion,field_cls = switch[node.type]
            val = conversion(node.value)

            if hasattr(field_cls, "__call__") and not type(field_cls) is type:
                field_cls = field_cls(val)

            field = field_cls()
            field._pfp__set_value(val)
            return field

        raise UnsupportedConstantType(node.coord, node.type)
733935
def handle(self,
               t_input: inference.TranslatorInput,
               t_output: inference.TranslatorOutput,
               t_walltime: float = 0.):
        
        alignments = " ".join(
            ["%d-%d" % (s, t) for s, t in get_alignments(t_output.attention_matrix, threshold=self.threshold)])
        self.stream.write("%s\t%s\n" % (t_output.translation, alignments))
        self.stream.flush()
569530
def parse_on_entry(self, node):
        

        event_handler = OnEntry()

        self.current_event_handler = event_handler
        self.current_regime.add_event_handler(event_handler)

        self.process_nested_tags(node)

        self.current_event_handler = None
551578
def _handle_continue(self, node, scope, ctxt, stream):
        
        self._dlog("handling continue")
        raise errors.InterpContinue()
975947
def nest(self, node, cls=None):
        

        if cls is None:
            cls = type(self)

        nested_scope = cls(node, self)
        self.children.append(nested_scope)
        return nested_scope
674718
def _handle_break(self, node, scope, ctxt, stream):
        
        self._dlog("handling break")
        raise errors.InterpBreak()
569771
def _handle_func_call(self, node, scope, ctxt, stream):
        
        self._dlog("handling function call to '{}'".format(node.name.name))
        if node.args is None:
            func_args = []
        else:
            func_args = self._handle_node(node.args, scope, ctxt, stream)
        func = self._handle_node(node.name, scope, ctxt, stream)
        return func.call(func_args, ctxt, scope, stream, self, node.coord)
727609
def _handle_decl_list(self, node, scope, ctxt, stream):
        
        self._dlog("handling decl list")
        # just handle each declaration
        for decl in node.decls:
            self._handle_node(decl, scope, ctxt, stream)
1293844
def visit_assign(self, node, parent):
        """"""
        type_annotation = self.check_type_comment(node)
        newnode = nodes.Assign(node.lineno, node.col_offset, parent)
        newnode.postinit(
            targets=[self.visit(child, newnode) for child in node.targets],
            value=self.visit(node.value, newnode),
            type_annotation=type_annotation,
        )
        return newnode
1128181
function AssignmentExpression(node, parent, scope, remaps) {
    var ids = this.getBindingIdentifiers();
    for (var name in ids) {
      replace(ids[name], node, scope, remaps);
    }
  }
871097
def _handle_typedef(self, node, scope, ctxt, stream):
        
        is_union_or_struct = (node.type.type.__class__ in [AST.Union, AST.Struct])
        is_enum = (node.type.type.__class__ is AST.Enum)

        if is_union_or_struct:
            self._dlog("handling typedef struct/union '{}'".format(node.name))
            scope.add_type_struct_or_union(node.name, self, node.type.type)
        elif is_enum:
            enum_cls = self._handle_node(node.type, scope, ctxt, stream)
            scope.add_type_class(node.name, enum_cls)
        elif isinstance(node.type, AST.ArrayDecl):
            # this does not parse data, just creates the ArrayDecl class
            array_cls = self._handle_node(node.type, scope, ctxt, stream)
            scope.add_type_class(node.name, array_cls)
        else:
            names = node.type.type.names

            self._dlog("handling typedef '{}' ({})".format(node.name, names))
            # don't actually handle the TypeDecl and Identifier nodes,
            # just directly add the types. Example structure:
            #
            #     Typedef: BLAH, [], ['typedef']
            #        TypeDecl: BLAH, []
            #            IdentifierType: ['unsigned', 'char']
            #    
            scope.add_type(node.name, names)
848449
def visit_Assign(self, node):
    """"""
    if len(node.targets) != 1:
      raise ValueError('no support for chained assignment')

    # Before the node gets modified, get a source code representation
    # to add as a comment later on
    if anno.hasanno(node, 'pre_anf'):
      orig_src = anno.getanno(node, 'pre_anf')
    else:
      orig_src = quoting.unquote(node)

    # Set target for the RHS visitor to access
    self.orig_target = ast_.copy_node(node.targets[0])

    # If we know we're going to be putting another stack on the stack,
    # we should try to make that explicit
    if isinstance(node.value, gast.Call) and \
        anno.hasanno(node.value, 'func') and \
        anno.getanno(node.value, 'func') in (utils.Stack, utils.pop_stack):
      push, pop, op_id = get_push_pop_stack()
    else:
      push, pop, op_id = get_push_pop()
    push_stack, pop_stack, op_id_stack = get_push_pop_stack()

    # Every assignment statement requires us to store the pre-value, and in the
    # adjoint restore the value, and reset the gradient
    store = template.replace(
        'push(_stack, y, op_id)',
        push=push,
        y=self.orig_target,
        _stack=self.stack,
        op_id=op_id)
    create_substack = template.replace(
        'substack = tangent.Stack()', substack=self.substack)
    store_substack = template.replace(
        'push(stack, substack, op_id)',
        push=push_stack,
        stack=self.stack,
        substack=self.substack,
        op_id=op_id_stack)
    restore = template.replace(
        'y = pop(_stack, op_id)',
        _stack=self.stack,
        pop=pop,
        y=ast_.copy_node(self.orig_target),
        op_id=op_id)
    restore_substack = template.replace(
        'substack = pop(stack, op_id)',
        pop=pop_stack,
        stack=self.stack,
        substack=self.substack,
        op_id=op_id_stack)
    reset = template.replace(
        'd[y] = init_grad(y, allow_lazy_initializer=True)',
        y=self.orig_target,
        init_grad=utils.INIT_GRAD,
        namer=self.namer,
        replace_grad=template.Replace.FULL)

    # If there are no active nodes, we don't need to find an adjoint
    # We simply store and restore the state, and reset the gradient
    if not self.is_active(node):
      return [store, node], [restore, reset]

    # We create a temporary variable for the target that the RHS can use
    self.target = create.create_temp(self.orig_target, self.namer)
    create_tmp = template.replace(
        'tmp = y', tmp=self.target, y=self.orig_target)

    # Get the primal and adjoint of the RHS expression
    try:
      fx, adjoint_rhs = self.visit(node.value)
    except ValueError as e:
      context = [t.id if hasattr(t, 'id') else t for t in node.targets]
      raise ValueError(
          'Failed to process assignment to: %s. Error: %s' % (context, e))
    if not isinstance(adjoint_rhs, list):
      adjoint_rhs = [adjoint_rhs]

    # Walk the RHS adjoint AST to find temporary adjoint variables to sum
    accumulations = []
    for n in adjoint_rhs:
      for succ in gast.walk(n):
        if anno.hasanno(succ, 'temp_adjoint_var'):
          xi = anno.getanno(succ, 'temp_adjoint_var')
          dxi_partial = ast_.copy_node(succ)
          accumulations.append(template.replace(
              'd[xi] = add_grad(d[xi], dxi_partial)',
              namer=self.namer, replace_grad=template.Replace.FULL,
              xi=xi, dxi_partial=dxi_partial, add_grad=utils.ADD_GRAD))

    # The primal consists of storing the state and then performing the
    # assignment with the new primal.
    # The primal `fx` may be optionally (but rarely) redefined when the
    # adjoint is generated, in `fx, adjoint_rhs = self.visit(node.value)`.
    # If we see that the primal value is an Assign node, or a list of nodes
    # (with at least one being an Assign) node, we allow the primal to change.
    # Otherwise, we'll build our own Assign node.
    if isinstance(fx, gast.Assign):
      assign = [fx]
    elif (isinstance(fx, list) and
          any([isinstance(ifx, gast.Assign) for ifx in fx])):
      assign = fx
    else:
      assign = template.replace(
          'y = fx', y=ast_.copy_node(self.orig_target), fx=fx)
      assign = [assign]
    primal = [store, create_substack, store_substack] + assign

    # The adjoint involves creating the temporary, restoring the store,
    # calculating the adjoint, resetting the gradient, and finally accumulating
    # the partials
    adjoint = [create_tmp, restore_substack, restore
              ] + adjoint_rhs + [reset] + accumulations

    # If the LHS is a subscript assignment with variable index, we need to
    # store and restore that as well
    if (isinstance(self.orig_target, gast.Subscript) and
        isinstance(self.orig_target.slice.value, gast.Name)):
      push, pop, op_id = get_push_pop()
      i = self.orig_target.slice.value
      push_index = template.replace(
          'push(_stack, i, op_id)',
          push=push,
          i=i,
          _stack=self.stack,
          op_id=op_id)
      pop_index = template.replace(
          'i = pop(_stack, op_id)',
          pop=pop,
          i=i,
          _stack_=self.stack,
          op_id=op_id)

      primal.insert(len(primal), push_index)
      adjoint.insert(0, pop_index)

    # Add a comment in the backwards pass, indicating which
    # lines in the forward pass generated the adjoint
    for i, adj in enumerate(adjoint):
      adjoint[i] = comments.add_comment(adj, 'Grad of: %s' % orig_src)

    return primal, adjoint
266376
def visit_Assign(self, node):
        
        value_deps = self.visit(node.value)
        for target in node.targets:
            name = get_variable(target)
            if isinstance(name, ast.Name):
                self.naming[name.id] = value_deps