constructor (object, index, value) {
      super()
      this.object = object
      this.index = value ? index : null
      this.value = value || index

      // validate input
      if (!isSymbolNode(object) && !isAccessorNode(object)) {
        throw new TypeError('SymbolNode or AccessorNode expected as "object"')
      }
      if (isSymbolNode(object) && object.name === 'end') {
        throw new Error('Cannot assign to symbol "end"')
      }
      if (this.index && !isIndexNode(this.index)) { // index is optional
        throw new TypeError('IndexNode expected as "index"')
      }
      if (!isNode(this.value)) {
        throw new TypeError('Node expected as "value"')
      }
    }
@constructor AssignmentNode
@extends {Node}

Define a symbol, like `a=3.2`, update a property like `a.b=3.2`, or
replace a subset of a matrix like `A[2,2]=42`.

Syntax:

    new AssignmentNode(symbol, value)
    new AssignmentNode(object, index, value)

Usage:

   new AssignmentNode(new SymbolNode('a'), new ConstantNode(2))  // a=2
   new AssignmentNode(new SymbolNode('a'),
                      new IndexNode('b'),
                      new ConstantNode(2))   // a.b=2
   new AssignmentNode(new SymbolNode('a'),
                      new IndexNode(1, 2),
                      new ConstantNode(3))  // a[1,2]=3

@param {SymbolNode | AccessorNode} object
    Object on which to assign a value
@param {IndexNode} [index=null]
    Index, property name or matrix index. Optional. If not provided
    and `object` is a SymbolNode, the property is assigned to the
    global scope.
@param {Node} value
    The value to be assigned