code: func doDemangle(name string, options ...Option) (ret AST, err error) {
  	// When the demangling routines encounter an error, they panic
  	// with a value of type demangleErr.
  	defer func() {
  		if r := recover(); r != nil {
  			if de, ok := r.(demangleErr); ok {
  				ret = nil
  				err = de
  				return
  			}
  			panic(r)
  		}
  	}()
  
  	params := true
  	clones := true
  	verbose := false
  	for _, o := range options {
  		switch o {
  		case NoParams:
  			params = false
  			clones = false
  		case NoTemplateParams:
  		// This is a valid option but only affect printing of the AST.
  		case NoClones:
  			clones = false
  		case Verbose:
  			verbose = true
  		default:
  			return nil, fmt.Errorf("unrecognized demangler option %v", o)
  		}
  	}
  
  	st := &state{str: name, verbose: verbose}
  	a := st.encoding(params, notForLocalName)
  
  	// Accept a clone suffix.
  	if clones {
  		for len(st.str) > 1 && st.str[0] == '.' && (isLower(st.str[1]) || st.str[1] == '_' || isDigit(st.str[1])) {
  			a = st.cloneSuffix(a)
  		}
  	}
  
  	if clones && len(st.str) > 0 {
  		st.fail("unparsed characters at end of mangled name")
  	}
  
  	return a, nil
  }
docs: // The doDemangle function is the entry point into the demangler proper.