index.js
function generateStraitsFunctions( {template}, path ) {
	// testTraitSet( traitSet )
	// it makes sure that all the `use traits * from` statements have a valid object as expression
	const testTraitBuilder = template(`
function TEST_TRAIT_SET( traitSet ) {
	if( ! traitSet || typeof traitSet === 'boolean' || typeof traitSet === 'number' || typeof traitSet === 'string' ) {
		throw new Error(\`\${traitSet} cannot be used as a trait set.\`);
	}
}
	`);

	// getSymbol( targetSymName, ...traits )
	// looks for `targetSymName` inside `traits`, and returns the symbol, if found
	const getSymbolBuilder = template(`
function GET_SYMBOL( targetSymName, ...traitSets ) {
	let symbol;
	traitSets.forEach( traitSet=>{
		const sym = traitSet[targetSymName];
		if( typeof sym === 'symbol' ) {
			if( !! symbol && symbol !== sym ) {
				throw new Error(\`Symbol \${targetSymName} offered by multiple trait sets.\`);
			}
			symbol = sym;
		}
	});
	if( ! symbol ) {
		throw new Error(\`No trait set is providing symbol \${targetSymName}.\`);
	}
	return symbol;
}
	`);

	// implSymbol( target, sym, value ): `target.*[sym] = value`
	const implSymbolBuilder = template(`
function IMPL_SYMBOL( target, sym, value ) {
	Object.defineProperty( target, sym, {value, configurable:true} );
	return target[sym];
}
	`);

	// generating identifiers for the above functions
	const identifiers = {
		testTraitSet: path.scope.generateUidIdentifier(`testTraitSet`),
		getSymbol: path.scope.generateUidIdentifier(`getSymbol`),
		implSymbol: path.scope.generateUidIdentifier(`implSymbol`),
	};

	// adding to the AST the code for the above functions
	path.unshiftContainer('body', testTraitBuilder({ TEST_TRAIT_SET:identifiers.testTraitSet }) );
	path.unshiftContainer('body', getSymbolBuilder({ GET_SYMBOL:identifiers.getSymbol }) );
	path.unshiftContainer('body', implSymbolBuilder({ IMPL_SYMBOL:identifiers.implSymbol }) );

	// returning the identifiers
	return identifiers;
}
function generateStraitsFunctions( {template}, path ) {
	// testTraitSet( traitSet )
	// it makes sure that all the `use traits * from` statements have a valid object as expression
	const testTraitBuilder = template(`
function TEST_TRAIT_SET( traitSet ) {
	if( ! traitSet || typeof traitSet === 'boolean' || typeof traitSet === 'number' || typeof traitSet === 'string' ) {
		throw new Error(\`\${traitSet} cannot be used as a trait set.\`);
	}
}
	`);

	// getSymbol( targetSymName, ...traits )
	// looks for `targetSymName` inside `traits`, and returns the symbol, if found
	const getSymbolBuilder = template(`
function GET_SYMBOL( targetSymName, ...traitSets ) {
	let symbol;
	traitSets.forEach( traitSet=>{
		const sym = traitSet[targetSymName];
		if( typeof sym === 'symbol' ) {
			if( !! symbol && symbol !== sym ) {
				throw new Error(\`Symbol \${targetSymName} offered by multiple trait sets.\`);
			}
			symbol = sym;
		}
	});
	if( ! symbol ) {
		throw new Error(\`No trait set is providing symbol \${targetSymName}.\`);
	}
	return symbol;
}
	`);

	// implSymbol( target, sym, value ): `target.*[sym] = value`
	const implSymbolBuilder = template(`
function IMPL_SYMBOL( target, sym, value ) {
	Object.defineProperty( target, sym, {value, configurable:true} );
	return target[sym];
}
	`);

	// generating identifiers for the above functions
	const identifiers = {
		testTraitSet: path.scope.generateUidIdentifier(`testTraitSet`),
		getSymbol: path.scope.generateUidIdentifier(`getSymbol`),
		implSymbol: path.scope.generateUidIdentifier(`implSymbol`),
	};

	// adding to the AST the code for the above functions
	path.unshiftContainer('body', testTraitBuilder({ TEST_TRAIT_SET:identifiers.testTraitSet }) );
	path.unshiftContainer('body', getSymbolBuilder({ GET_SYMBOL:identifiers.getSymbol }) );
	path.unshiftContainer('body', implSymbolBuilder({ IMPL_SYMBOL:identifiers.implSymbol }) );

	// returning the identifiers
	return identifiers;
}
function generateStraitsFunctions ( { template } , path ) { // testTraitSet( traitSet ) // it makes sure that all the `use traits * from` statements have a valid object as expression const testTraitBuilder = template ( ` \` \$ \` ` ) ; // getSymbol( targetSymName, ...traits ) // looks for `targetSymName` inside `traits`, and returns the symbol, if found const getSymbolBuilder = template ( ` \` \$ \` \` \$ \` ` ) ; // implSymbol( target, sym, value ): `target.*[sym] = value` const implSymbolBuilder = template ( ` ` ) ; // generating identifiers for the above functions const identifiers = { testTraitSet : path . scope . generateUidIdentifier ( ` ` ) , getSymbol : path . scope . generateUidIdentifier ( ` ` ) , implSymbol : path . scope . generateUidIdentifier ( ` ` ) , } ; // adding to the AST the code for the above functions path . unshiftContainer ( 'body' , testTraitBuilder ( { TEST_TRAIT_SET : identifiers . testTraitSet } ) ) ; path . unshiftContainer ( 'body' , getSymbolBuilder ( { GET_SYMBOL : identifiers . getSymbol } ) ) ; path . unshiftContainer ( 'body' , implSymbolBuilder ( { IMPL_SYMBOL : identifiers . implSymbol } ) ) ; // returning the identifiers return identifiers ; }
prepend to `path` the functions we need to use traits
prepend to path the functions we need to use traits