docs: function use_dialect(dialectOrName, lexer, options) {
  
    options = options || {};
    var dialect;
    var dialectName;
    if(typeof dialectOrName === 'string') {
      dialectName = dialectOrName;
    }
    else {
      dialect = dialectOrName;
    }
  
    // we only allow one of each "file level" dialect...
    if(!options.local) {
      var alreadyLoadedDialect;
      if(dialectName) {
        // has this named dialect already been loaded?
        alreadyLoadedDialect = lexer.dialects.find(function(dialect) {
          return(dialect.name === dialectName);
        });
      }
      else {
        // has this dialect object already been loaded?
        alreadyLoadedDialect = (lexer.dialects.indexOf(dialect) !== -1);
      }
  
      // note they can optionally pass options.reload to *force* a reload
      if(alreadyLoadedDialect && !options.reload)
      {
        // just give back the previously loaded file-level dialect
        return alreadyLoadedDialect;
      }
    }
  
    // note there's some circular dependency issues if dialect-loader
    // is requried at the top of this reader.js file - but it doesn't happen here
    slinfo('using dialect:', dialectName ? dialectName :
                      (dialect && dialect.name ? dialect.name : "?"));
    if(!dialect) {
      dialect = options.preloaded || require('./dialect-loader').load(dialectName);
    }
  
    // Make sure any dialects this one extends are loaded first
    if(dialect.extends) {
      var extendsArr = (Array.isArray(dialect.extends) ?
                          dialect.extends : [dialect.extends]);
      extendsArr.forEach(function(baseDialectName) {
        use_dialect(baseDialectName, lexer, options);
      });
    }
  
    // make sure the dialect provides something to work with...
    if(!dialect.lextab && !dialect.readtab && !dialect.gentab ) {
      lexer.error("System error: malformed language extension \"" + dialectName + "\"");
    }
  
    // but otherwise the lex/read/generate tables are all optional:
    // (e.g. they might be using just one of the three)
    dialect.lextab = dialect.lextab || [];
    dialect.readtab = dialect.readtab || {};
    dialect.gentab = dialect.gentab || {};
  
    // cull a list of non-parenthesized infix/prefix/suffix "operators"...
    // later "read" transforms these based on precedence (i.e. TDOP "binding powers").
    // note: though here in core, this is mostly for the benefit of the
    //   the "sugared" dialects (e.g. plus and sugarscript).  Since core
    //   is a true lisp it doesn't define infix/prefix/suffix "operators".
    dialect.readtab.__operators = {};
    Object.keys(dialect.readtab).forEach(function(sym) {
      var readfn = dialect.readtab[sym];
      if(readfn.operator) {
        dialect.readtab.__operators[sym] = readfn;
      }
    });
    dialect.readtab.__operatorsymbols = Object.keys(dialect.readtab.__operators);
  
    // onuse is an optional file containing js to insert in the output
    // at the point of #use.
    // (this may support lispy code in the future but for now we require js)
    if(typeof options.onusecode === 'undefined' || options.onusecode) {
      if(dialect.onuse) {
        dialect.onusecode = read_include_file(dialect.onuse, lexer);
      }
    }
  
    // Make the new dialect visible within this file
    lexer.push_dialect(dialect);
  
    // invoke the (optional) dialect initialization functions:
    invokeInitDialectFunctions(dialect, lexer, options);
  
    // return the newly loaded and prepped dialect
    return dialect;
  }