code: func (r *RawConfig) Interpolate(vs map[string]ast.Variable) error {
  	r.lock.Lock()
  	defer r.lock.Unlock()
  
  	config := langEvalConfig(vs)
  	return r.interpolate(func(root ast.Node) (interface{}, error) {
  		// None of the variables we need are computed, meaning we should
  		// be able to properly evaluate.
  		result, err := hil.Eval(root, config)
  		if err != nil {
  			return "", err
  		}
  
  		return result.Value, nil
  	})
  }
docs: // Interpolate uses the given mapping of variable values and uses
  // those as the values to replace any variables in this raw
  // configuration.
  //
  // Any prior calls to Interpolate are replaced with this one.
  //
  // If a variable key is missing, this will panic.