composer.js
function declare (combinators, prefix) {
  if (arguments.length > 2) throw new ComposerError('Too many arguments in "declare"')
  if (!isObject(combinators)) throw new ComposerError('Invalid argument "combinators" in "declare"', combinators)
  if (prefix !== undefined && typeof prefix !== 'string') throw new ComposerError('Invalid argument "prefix" in "declare"', prefix)
  const composer = {}
  for (let key in combinators) {
    const type = prefix ? prefix + '.' + key : key
    const combinator = combinators[key]
    if (!isObject(combinator) || (combinator.args !== undefined && !Array.isArray(combinator.args))) {
      throw new ComposerError(`Invalid "${type}" combinator specification in "declare"`, combinator)
    }
    for (let arg of combinator.args || []) {
      if (typeof arg.name !== 'string') throw new ComposerError(`Invalid "${type}" combinator specification in "declare"`, combinator)
    }
    composer[key] = function () {
      const composition = { type, '.combinator': () => combinator }
      const skip = (combinator.args && combinator.args.length) || 0
      if (!combinator.components && (arguments.length > skip)) {
        throw new ComposerError(`Too many arguments in "${type}" combinator`)
      }
      for (let i = 0; i < skip; ++i) {
        composition[combinator.args[i].name] = arguments[i]
      }
      if (combinator.components) {
        composition.components = Array.prototype.slice.call(arguments, skip)
      }
      return new Composition(composition)
    }
  }
  return composer
}
function declare (combinators, prefix) {
  if (arguments.length > 2) throw new ComposerError('Too many arguments in "declare"')
  if (!isObject(combinators)) throw new ComposerError('Invalid argument "combinators" in "declare"', combinators)
  if (prefix !== undefined && typeof prefix !== 'string') throw new ComposerError('Invalid argument "prefix" in "declare"', prefix)
  const composer = {}
  for (let key in combinators) {
    const type = prefix ? prefix + '.' + key : key
    const combinator = combinators[key]
    if (!isObject(combinator) || (combinator.args !== undefined && !Array.isArray(combinator.args))) {
      throw new ComposerError(`Invalid "${type}" combinator specification in "declare"`, combinator)
    }
    for (let arg of combinator.args || []) {
      if (typeof arg.name !== 'string') throw new ComposerError(`Invalid "${type}" combinator specification in "declare"`, combinator)
    }
    composer[key] = function () {
      const composition = { type, '.combinator': () => combinator }
      const skip = (combinator.args && combinator.args.length) || 0
      if (!combinator.components && (arguments.length > skip)) {
        throw new ComposerError(`Too many arguments in "${type}" combinator`)
      }
      for (let i = 0; i < skip; ++i) {
        composition[combinator.args[i].name] = arguments[i]
      }
      if (combinator.components) {
        composition.components = Array.prototype.slice.call(arguments, skip)
      }
      return new Composition(composition)
    }
  }
  return composer
}
function declare ( combinators , prefix ) { if ( arguments . length > 2 ) throw new ComposerError ( 'Too many arguments in "declare"' ) if ( ! isObject ( combinators ) ) throw new ComposerError ( 'Invalid argument "combinators" in "declare"' , combinators ) if ( prefix !== undefined && typeof prefix !== 'string' ) throw new ComposerError ( 'Invalid argument "prefix" in "declare"' , prefix ) const composer = { } for ( let key in combinators ) { const type = prefix ? prefix + '.' + key : key const combinator = combinators [ key ] if ( ! isObject ( combinator ) || ( combinator . args !== undefined && ! Array . isArray ( combinator . args ) ) ) { throw new ComposerError ( ` ${ type } ` , combinator ) } for ( let arg of combinator . args || [ ] ) { if ( typeof arg . name !== 'string' ) throw new ComposerError ( ` ${ type } ` , combinator ) } composer [ key ] = function ( ) { const composition = { type , '.combinator' : ( ) => combinator } const skip = ( combinator . args && combinator . args . length ) || 0 if ( ! combinator . components && ( arguments . length > skip ) ) { throw new ComposerError ( ` ${ type } ` ) } for ( let i = 0 ; i < skip ; ++ i ) { composition [ combinator . args [ i ] . name ] = arguments [ i ] } if ( combinator . components ) { composition . components = Array . prototype . slice . call ( arguments , skip ) } return new Composition ( composition ) } } return composer }
derive combinator methods from combinator table check argument count and map argument positions to argument names delegate to Composition constructor for the rest of the validation
derive combinator methods from combinator table check argument count and map argument positions to argument names delegate to Composition constructor for the rest of the validation