code: func (p *CopyPropagator) updateBindings(pctx *plugContext, expr *ast.Expr) bool {
  	if pctx.negated || len(expr.With) > 0 {
  		return true
  	}
  	if expr.IsEquality() {
  		a, b := expr.Operand(0), expr.Operand(1)
  		if a.Equal(b) {
  			return false
  		}
  		k, v, keep := p.updateBindingsEq(a, b)
  		if !keep {
  			if v != nil {
  				pctx.bindings[k] = newbinding(k, v)
  			}
  			return false
  		}
  	} else if expr.IsCall() {
  		terms := expr.Terms.([]*ast.Term)
  		output := terms[len(terms)-1]
  		if k, ok := output.Value.(ast.Var); ok && !p.livevars.Contains(k) && !pctx.headvars.Contains(k) {
  			pctx.bindings[k] = newbinding(k, ast.CallTerm(terms[:len(terms)-1]...).Value)
  			return false
  		}
  	}
  	return !isNoop(expr)
  }
docs: // updateBindings returns false if the expression can be killed. If the
  // expression is killed, the binding list is updated to map a var to value.