shared/schema.js
function computeParamTypes(rel, bindingTypes, implicits, computeTypeWrapper){
	_.assertLength(arguments, 4)
	_.assertArray(implicits)
	rel.params.forEach(function(p){
		if(p.type === 'macro' || p.type === 'partial-application'){
			return
		}
		computeTypeWrapper(p, bindingTypes, implicits)
	})
}
function computeParamTypes(rel, bindingTypes, implicits, computeTypeWrapper){
	_.assertLength(arguments, 4)
	_.assertArray(implicits)
	rel.params.forEach(function(p){
		if(p.type === 'macro' || p.type === 'partial-application'){
			return
		}
		computeTypeWrapper(p, bindingTypes, implicits)
	})
}
/*
function computePathResultType(path, baseType, context, schema, viewMap){
_.assertLength(arguments, 5);
_.assertObject(baseType);
var t = baseType;
_.each(path, function(p){
if(p.type === 'property'){
_.errout('TODO?')
t = t.properties[p.property];
if(t === undefined){
_.errout('unknown property: ' + p.property);
}
_.assertObject(t);
}else if(p.type === 'macro'){
_.errout('TODO?')
var input = t;
t = computeType(p.expr, context, schema, viewMap);
if(input.type.type === 'set'){
_.assert(t.type !== 'set' && t.type !== 'list')
t = {type: 'set', members: t};
}else if(input.type.type === 'list'){
t = {type: 'list', members: t};
}
_.assertObject(t);
}else{
_.errout('TODO support path part type: ' + p.type);
}
});
return t;
}