function applyGenericOperatorIndex(r, schema, parent){
	if(r.type === 'view'){

		if(r.view === 'reducing-index') return r

		if( r.view !== 'case' && r.view !== 'default' && //do not break switch statements
			r.view !== 'map' && r.view !== 'multimap'// do not break mapValue(map()) exprs
			&& r.view !== 'mapValue'
			&& r.view !== 'property' //no point wrapping a redundant index
			&& r.view !== 'cast' //no point TODO flip this to an explicit "heavy" tag that causes indexing
			&& r.view !== 'type' //not worth it
			&& r.view !== 'timestamp' //not worth it
			&& r.view !== 'list' //not worth it
			&& r.view !== 'isa' //not worth it
			&& r.view !== 'not' //not worth it
			&& r.view !== 'generic-operator-index' //obv
			&& (!parent || parent.view !== 'generic-operator-index') //obv
			&& !schema[r.view] //don't index object(id) lookups - they're a no-op anyway
			){

			var params = getParams(r, schema)
			//console.log(r.view + ' ' + JSON.stringify(params))
			//if(r.view !== 'property' || r.params[1] !== params[0]){
				if(params.length === 1){
				
					if(canIndex(r, schema, params[0])){
						//console.log('cannot index: ')
						//if(r.view === 'tokenizeAndStemText') _.errout('TODO: ' + JSON.stringify(r, null, 2))
						//return r
					
				
						var indexExprs = getIndexes(r, params[0])
						var res = {
							type: 'view',
							view: 'generic-operator-index',
							params: [
								params[0],
								r
							].concat(indexExprs),
							schemaType: r.schemaType,
							code: r.code
						}
						//console.log('res: ' + JSON.stringify(res, null, 2))
						return res
					}
				}else if(params.length > 1 && r.params.length === 1 && r.params[0].view === 'property'){//there are multiple params in use, but they can be reduced to a single param via a 'let' externalization
				
					var name = 'extracted_for_goi_'+Math.random()
					var expr = r.params[0].params[1]
					var newParam = {type: 'param', name: name, schemaType: expr.schemaType, was: expr}
					
					var newPropertyExpr = {
						type: 'view',
						view: 'property',
						params: [
							r.params[0].params[0],
							newParam
						],
						schemaType: r.schemaType
					}
					
					var res = {
						type: 'let',
						//view: 'let',
						expr: expr,
						rest: {
							type: 'view',
							view: 'generic-operator-index',
							params: [
								newParam,
								{
									type: 'view',
									view: r.view,
									params: [newPropertyExpr],
									schemaType: r.schemaType
								},
								newPropertyExpr
							]
						},
						name: name,
						schemaType: r.schemaType,
						code: r.code
					}
					
					//res.expr = applyGenericOperatorIndex(res.expr, schema)//?
					
					return res
				}
			//}
		}
		
		if(r.view === 'tokenizeAndStemText') _.errout('TODO: ' + JSON.stringify(r, null, 2))

		if(r.view === 'generic-operator-index') return r
		
		r.params.forEach(function(p,i){
			r.params[i] = applyGenericOperatorIndex(p, schema, r)
		})
	}else if(r.type === 'let'){
		r.expr = applyGenericOperatorIndex(r.expr, schema)
		r.rest = applyGenericOperatorIndex(r.rest, schema)
	}else if(r.type === 'macro'){
		r.expr = applyGenericOperatorIndex(r.expr, schema)
	}else if(r.type === 'param' || r.type === 'value' || r.type === 'int' || r.type === 'nil'){
		//do nothing

	}
	if(r.view === 'tokenizeAndStemText') _.errout('TODO: ' + JSON.stringify(r, null, 2))
	return r
}
function applyGenericOperatorIndex(r, schema, parent){
	if(r.type === 'view'){

		if(r.view === 'reducing-index') return r

		if( r.view !== 'case' && r.view !== 'default' && 
			r.view !== 'map' && r.view !== 'multimap'
			&& r.view !== 'mapValue'
			&& r.view !== 'property' 
			&& r.view !== 'cast' 
			&& r.view !== 'type' 
			&& r.view !== 'timestamp' 
			&& r.view !== 'list' 
			&& r.view !== 'isa' 
			&& r.view !== 'not' 
			&& r.view !== 'generic-operator-index' 
			&& (!parent || parent.view !== 'generic-operator-index') 
			&& !schema[r.view] 
			){

			var params = getParams(r, schema)
			
			
				if(params.length === 1){
				
					if(canIndex(r, schema, params[0])){
						
						
						
					
				
						var indexExprs = getIndexes(r, params[0])
						var res = {
							type: 'view',
							view: 'generic-operator-index',
							params: [
								params[0],
								r
							].concat(indexExprs),
							schemaType: r.schemaType,
							code: r.code
						}
						
						return res
					}
				}else if(params.length > 1 && r.params.length === 1 && r.params[0].view === 'property'){
				
					var name = 'extracted_for_goi_'+Math.random()
					var expr = r.params[0].params[1]
					var newParam = {type: 'param', name: name, schemaType: expr.schemaType, was: expr}
					
					var newPropertyExpr = {
						type: 'view',
						view: 'property',
						params: [
							r.params[0].params[0],
							newParam
						],
						schemaType: r.schemaType
					}
					
					var res = {
						type: 'let',
						
						expr: expr,
						rest: {
							type: 'view',
							view: 'generic-operator-index',
							params: [
								newParam,
								{
									type: 'view',
									view: r.view,
									params: [newPropertyExpr],
									schemaType: r.schemaType
								},
								newPropertyExpr
							]
						},
						name: name,
						schemaType: r.schemaType,
						code: r.code
					}
					
					
					
					return res
				}
			
		}
		
		if(r.view === 'tokenizeAndStemText') _.errout('TODO: ' + JSON.stringify(r, null, 2))

		if(r.view === 'generic-operator-index') return r
		
		r.params.forEach(function(p,i){
			r.params[i] = applyGenericOperatorIndex(p, schema, r)
		})
	}else if(r.type === 'let'){
		r.expr = applyGenericOperatorIndex(r.expr, schema)
		r.rest = applyGenericOperatorIndex(r.rest, schema)
	}else if(r.type === 'macro'){
		r.expr = applyGenericOperatorIndex(r.expr, schema)
	}else if(r.type === 'param' || r.type === 'value' || r.type === 'int' || r.type === 'nil'){
		

	}
	if(r.view === 'tokenizeAndStemText') _.errout('TODO: ' + JSON.stringify(r, null, 2))
	return r
}
function applyGenericOperatorIndex ( r , schema , parent ) { if ( r . type === 'view' ) { if ( r . view === 'reducing-index' ) return r if ( r . view !== 'case' && r . view !== 'default' && //do not break switch statements r . view !== 'map' && r . view !== 'multimap' // do not break mapValue(map()) exprs && r . view !== 'mapValue' && r . view !== 'property' //no point wrapping a redundant index && r . view !== 'cast' //no point TODO flip this to an explicit "heavy" tag that causes indexing && r . view !== 'type' //not worth it && r . view !== 'timestamp' //not worth it && r . view !== 'list' //not worth it && r . view !== 'isa' //not worth it && r . view !== 'not' //not worth it && r . view !== 'generic-operator-index' //obv && ( ! parent || parent . view !== 'generic-operator-index' ) //obv && ! schema [ r . view ] //don't index object(id) lookups - they're a no-op anyway ) { var params = getParams ( r , schema ) //console.log(r.view + ' ' + JSON.stringify(params)) //if(r.view !== 'property' || r.params[1] !== params[0]){ if ( params . length === 1 ) { if ( canIndex ( r , schema , params [ 0 ] ) ) { //console.log('cannot index: ') //if(r.view === 'tokenizeAndStemText') _.errout('TODO: ' + JSON.stringify(r, null, 2)) //return r var indexExprs = getIndexes ( r , params [ 0 ] ) var res = { type : 'view' , view : 'generic-operator-index' , params : [ params [ 0 ] , r ] . concat ( indexExprs ) , schemaType : r . schemaType , code : r . code } //console.log('res: ' + JSON.stringify(res, null, 2)) return res } } else if ( params . length > 1 && r . params . length === 1 && r . params [ 0 ] . view === 'property' ) { //there are multiple params in use, but they can be reduced to a single param via a 'let' externalization var name = 'extracted_for_goi_' + Math . random ( ) var expr = r . params [ 0 ] . params [ 1 ] var newParam = { type : 'param' , name : name , schemaType : expr . schemaType , was : expr } var newPropertyExpr = { type : 'view' , view : 'property' , params : [ r . params [ 0 ] . params [ 0 ] , newParam ] , schemaType : r . schemaType } var res = { type : 'let' , //view: 'let', expr : expr , rest : { type : 'view' , view : 'generic-operator-index' , params : [ newParam , { type : 'view' , view : r . view , params : [ newPropertyExpr ] , schemaType : r . schemaType } , newPropertyExpr ] } , name : name , schemaType : r . schemaType , code : r . code } //res.expr = applyGenericOperatorIndex(res.expr, schema)//? return res } //} } if ( r . view === 'tokenizeAndStemText' ) _ . errout ( 'TODO: ' + JSON . stringify ( r , null , 2 ) ) if ( r . view === 'generic-operator-index' ) return r r . params . forEach ( function ( p , i ) { r . params [ i ] = applyGenericOperatorIndex ( p , schema , r ) } ) } else if ( r . type === 'let' ) { r . expr = applyGenericOperatorIndex ( r . expr , schema ) r . rest = applyGenericOperatorIndex ( r . rest , schema ) } else if ( r . type === 'macro' ) { r . expr = applyGenericOperatorIndex ( r . expr , schema ) } else if ( r . type === 'param' || r . type === 'value' || r . type === 'int' || r . type === 'nil' ) { //do nothing } if ( r . view === 'tokenizeAndStemText' ) _ . errout ( 'TODO: ' + JSON . stringify ( r , null , 2 ) ) return r }
/*
function shouldIndex(r){//TODO set up with .heavy = true config of impls, then start using
if(r.type === 'view'){
if(r.view === 'typeset'){
return false
}else if(r.view === 'each' || r.view === 'map' || r.view === 'eachReduce'){
return true
}
var should = false
r.params.forEach(function(p){
should = should || shouldIndex(p)
})
}else if(r.type === 'let'){
return shouldIndex(r.expr, param) || shouldIndex(r.rest)
}else if(r.type === 'macro'){
return shouldIndex(r.expr, param)
}else if(r.type === 'param'){
return false
}else if(r.type === 'value' || r.type === 'int' || r.type === 'nil'){
return false
}else{
_.errout('TODO')
}
}
/ * function shouldIndex ( r ) { // TODO set up with . heavy = true config of impls then start using if ( r . type === view ) { if ( r . view === typeset ) { return false } else if ( r . view === each || r . view === map || r . view === eachReduce ) { return true } var should = false r . params . forEach ( function ( p ) { should = should || shouldIndex ( p ) } ) } else if ( r . type === let ) { return shouldIndex ( r . expr param ) || shouldIndex ( r . rest ) } else if ( r . type === macro ) { return shouldIndex ( r . expr param ) } else if ( r . type === param ) { return false } else if ( r . type === value || r . type === int || r . type === nil ) { return false } else { _ . errout ( TODO ) } }