code: func (n *EvalWriteOutput) Eval(ctx EvalContext) (interface{}, error) {
  	addr := n.Addr.Absolute(ctx.Path())
  
  	// This has to run before we have a state lock, since evaluation also
  	// reads the state
  	val, diags := ctx.EvaluateExpr(n.Expr, cty.DynamicPseudoType, nil)
  	// We'll handle errors below, after we have loaded the module.
  
  	state := ctx.State()
  	if state == nil {
  		return nil, nil
  	}
  
  	changes := ctx.Changes() // may be nil, if we're not working on a changeset
  
  	// handling the interpolation error
  	if diags.HasErrors() {
  		if n.ContinueOnErr || flagWarnOutputErrors {
  			log.Printf("[ERROR] Output interpolation %q failed: %s", n.Addr.Name, diags.Err())
  			// if we're continuing, make sure the output is included, and
  			// marked as unknown. If the evaluator was able to find a type
  			// for the value in spite of the error then we'll use it.
  			n.setValue(addr, state, changes, cty.UnknownVal(val.Type()))
  			return nil, EvalEarlyExitError{}
  		}
  		return nil, diags.Err()
  	}
  
  	n.setValue(addr, state, changes, val)
  
  	return nil, nil
  }
docs: // TODO: test