code: func (r *RuleSet) Add(configSet, path string, cb Func) {
  	r.l.Lock()
  	defer r.l.Unlock()
  
  	// Pattern strings without ':' are magical: they are treated like exact
  	// matches. Thus if a variable value has ':', it may change the meaning of the
  	// pattern after the substitution. To avoid this, clarify the kind of the
  	// pattern before the substitution.
  	if !strings.ContainsRune(configSet, ':') {
  		configSet = "exact:" + configSet
  	}
  	if !strings.ContainsRune(path, ':') {
  		path = "exact:" + path
  	}
  
  	// Validate the patterns syntax by rendering them with some fake variable
  	// values.
  	nilSub := func(name string) (string, error) {
  		if r.v[name] == nil {
  			return "", fmt.Errorf("no placeholder named %q is registered", name)
  		}
  		// We have no context to actually render the placeholder. Substituting with
  		// empty string is good enough for the purpose of the preliminary pattern
  		// syntax validation.
  		return "", nil
  	}
  	if _, err := renderPatternString(configSet, nilSub); err != nil {
  		panic(fmt.Sprintf("bad config set pattern %q - %s", configSet, err))
  	}
  	if _, err := renderPatternString(path, nilSub); err != nil {
  		panic(fmt.Sprintf("bad path pattern %q - %s", path, err))
  	}
  
  	r.r = append(r.r, &rule{configSet, path, cb})
  }
docs: // Add registers a validation function for given configSet and path patterns.
  //
  // The pattern may contain placeholders (e.g. "${appid}") that will be
  // resolved before the actual validation starts. All such placeholder variables
  // must be registered prior to adding rules that reference them (or 'Add' will
  // panic).
  //
  // 'Add' will also try to validate the patterns by substituting all placeholders
  // in them with empty strings and trying to render the resulting pattern. It
  // will panic if the pattern is invalid.