2011-01-19 00:24:11 +01:00
/* sbt -- Simple Build Tool
* Copyright 2011 Mark Harrah
*/
2010-09-08 20:29:00 +02:00
package sbt
2010-12-29 22:07:17 +01:00
import Types._
2010-12-13 03:33:32 +01:00
sealed trait Settings [ Scope ]
{
2011-01-19 00:24:11 +01:00
def data : Map [ Scope , AttributeMap ]
def keys ( scope : Scope ) : Set [ AttributeKey [ _ ] ]
def scopes : Set [ Scope ]
2011-02-06 17:33:56 +01:00
def definingScope ( scope : Scope , key : AttributeKey [ _ ] ) : Option [ Scope ]
2011-01-26 04:19:03 +01:00
def allKeys [ T ] ( f : ( Scope , AttributeKey [ _ ] ) => T ) : Seq [ T ]
2010-12-13 03:33:32 +01:00
def get [ T ] ( scope : Scope , key : AttributeKey [ T ] ) : Option [ T ]
def set [ T ] ( scope : Scope , key : AttributeKey [ T ] , value : T ) : Settings [ Scope ]
}
2010-12-29 22:07:17 +01:00
private final class Settings0 [ Scope ] ( val data : Map [ Scope , AttributeMap ] , val delegates : Scope => Seq [ Scope ] ) extends Settings [ Scope ]
2010-09-08 20:29:00 +02:00
{
2011-01-19 00:24:11 +01:00
def scopes : Set [ Scope ] = data . keySet . toSet
def keys ( scope : Scope ) = data ( scope ) . keys . toSet
2011-01-26 04:19:03 +01:00
def allKeys [ T ] ( f : ( Scope , AttributeKey [ _ ] ) => T ) : Seq [ T ] = data . flatMap { case ( scope , map ) => map . keys . map ( k => f ( scope , k ) ) } toSeq ;
2010-12-29 22:07:17 +01:00
2010-12-13 03:33:32 +01:00
def get [ T ] ( scope : Scope , key : AttributeKey [ T ] ) : Option [ T ] =
2010-12-29 22:07:17 +01:00
delegates ( scope ) . toStream . flatMap ( sc => scopeLocal ( sc , key ) ) . headOption
2011-02-06 17:33:56 +01:00
def definingScope ( scope : Scope , key : AttributeKey [ _ ] ) : Option [ Scope ] =
delegates ( scope ) . toStream . filter ( sc => scopeLocal ( sc , key ) . isDefined ) . headOption
2010-12-13 03:33:32 +01:00
private def scopeLocal [ T ] ( scope : Scope , key : AttributeKey [ T ] ) : Option [ T ] =
( data get scope ) . flatMap ( _ get key )
def set [ T ] ( scope : Scope , key : AttributeKey [ T ] , value : T ) : Settings [ Scope ] =
{
val map = ( data get scope ) getOrElse AttributeMap . empty
val newData = data . updated ( scope , map . put ( key , value ) )
2010-12-29 22:07:17 +01:00
new Settings0 ( newData , delegates )
2010-12-13 03:33:32 +01:00
}
2010-09-08 20:29:00 +02:00
}
2010-12-29 22:07:17 +01:00
// delegates should contain the input Scope as the first entry
2011-01-19 00:24:11 +01:00
// this trait is intended to be mixed into an object
trait Init [ Scope ]
2010-09-08 20:29:00 +02:00
{
2011-04-14 01:04:53 +02:00
def display ( skey : ScopedKey [ _ ] ) : String
2010-12-29 22:07:17 +01:00
final case class ScopedKey [ T ] ( scope : Scope , key : AttributeKey [ T ] )
2010-09-08 20:29:00 +02:00
2010-12-29 22:07:17 +01:00
type SettingSeq [ T ] = Seq [ Setting [ T ] ]
type ScopedMap = IMap [ ScopedKey , SettingSeq ]
type CompiledMap = Map [ ScopedKey [ _ ] , Compiled ]
type MapScoped = ScopedKey ~> ScopedKey
2011-07-26 03:59:22 +02:00
type ValidatedRef [ T ] = Either [ Undefined , ScopedKey [ T ] ]
type ValidateRef = ScopedKey ~> ValidatedRef
2011-02-12 02:22:17 +01:00
type ScopeLocal = ScopedKey [ _ ] => Seq [ Setting [ _ ] ]
2011-07-20 03:29:05 +02:00
type MapConstant = ScopedKey ~> Option
2010-12-13 03:33:32 +01:00
2011-02-12 02:22:17 +01:00
def setting [ T ] ( key : ScopedKey [ T ] , init : Initialize [ T ] ) : Setting [ T ] = new Setting [ T ] ( key , init )
def value [ T ] ( value : => T ) : Initialize [ T ] = new Value ( value _ )
2011-05-08 04:02:06 +02:00
def optional [ T ,U ] ( key : ScopedKey [ T ] ) ( f : Option [ T ] => U ) : Initialize [ U ] = new Optional ( Some ( key ) , f )
2011-02-12 02:22:17 +01:00
def update [ T ] ( key : ScopedKey [ T ] ) ( f : T => T ) : Setting [ T ] = new Setting [ T ] ( key , app ( key : ^: KNil ) ( hl => f ( hl . head ) ) )
def app [ HL <: HList , T ] ( inputs : KList [ ScopedKey , HL ] ) ( f : HL => T ) : Initialize [ T ] = new Apply ( f , inputs )
def uniform [ S ,T ] ( inputs : Seq [ ScopedKey [ S ] ] ) ( f : Seq [ S ] => T ) : Initialize [ T ] = new Uniform ( f , inputs )
def kapp [ HL <: HList , M [ _ ] , T ] ( inputs : KList [ ( { type l [ t ] = ScopedKey [ M [ t ] ] } ) # l , HL ] ) ( f : KList [ M , HL ] => T ) : Initialize [ T ] = new KApply [ HL , M , T ] ( f , inputs )
2010-12-13 03:33:32 +01:00
2011-01-19 00:24:11 +01:00
// the following is a temporary workaround for the "... cannot be instantiated from ..." bug, which renders 'kapp' above unusable outside this source file
class KApp [ HL <: HList , M [ _ ] , T ] {
type Composed [ S ] = ScopedKey [ M [ S ] ]
2011-02-12 02:22:17 +01:00
def apply ( inputs : KList [ Composed , HL ] ) ( f : KList [ M , HL ] => T ) : Initialize [ T ] = new KApply [ HL , M , T ] ( f , inputs )
2011-01-19 00:24:11 +01:00
}
def empty ( implicit delegates : Scope => Seq [ Scope ] ) : Settings [ Scope ] = new Settings0 ( Map . empty , delegates )
2010-12-29 22:07:17 +01:00
def asTransform ( s : Settings [ Scope ] ) : ScopedKey ~> Id = new ( ScopedKey ~> Id ) {
2011-01-19 00:24:11 +01:00
def apply [ T ] ( k : ScopedKey [ T ] ) : T = getValue ( s , k )
2010-12-13 03:33:32 +01:00
}
2011-04-28 02:40:52 +02:00
def getValue [ T ] ( s : Settings [ Scope ] , k : ScopedKey [ T ] ) = s . get ( k . scope , k . key ) getOrElse error ( "Internal settings error: invalid reference to " + display ( k ) )
2011-01-19 00:24:11 +01:00
def asFunction [ T ] ( s : Settings [ Scope ] ) : ScopedKey [ T ] => T = k => getValue ( s , k )
2010-12-13 03:33:32 +01:00
2011-03-30 02:25:12 +02:00
def compiled ( init : Seq [ Setting [ _ ] ] , actual : Boolean = true ) ( implicit delegates : Scope => Seq [ Scope ] , scopeLocal : ScopeLocal ) : CompiledMap =
2010-12-13 03:33:32 +01:00
{
2011-02-06 17:33:56 +01:00
// prepend per-scope settings
2011-02-06 03:39:34 +01:00
val withLocal = addLocal ( init ) ( scopeLocal )
2010-12-29 22:07:17 +01:00
// group by Scope/Key, dropping dead initializations
2011-02-06 03:39:34 +01:00
val sMap : ScopedMap = grouped ( withLocal )
2010-12-29 22:07:17 +01:00
// delegate references to undefined values according to 'delegates'
2011-03-30 02:25:12 +02:00
val dMap : ScopedMap = if ( actual ) delegate ( sMap ) ( delegates ) else sMap
2010-12-29 22:07:17 +01:00
// merge Seq[Setting[_]] into Compiled
2011-02-06 17:33:56 +01:00
compile ( dMap )
}
2011-02-12 02:22:17 +01:00
def make ( init : Seq [ Setting [ _ ] ] ) ( implicit delegates : Scope => Seq [ Scope ] , scopeLocal : ScopeLocal ) : Settings [ Scope ] =
2011-02-06 17:33:56 +01:00
{
val cMap = compiled ( init ) ( delegates , scopeLocal )
2010-12-29 22:07:17 +01:00
// order the initializations. cyclic references are detected here.
val ordered : Seq [ Compiled ] = sort ( cMap )
// evaluation: apply the initializations.
applyInits ( ordered )
2010-12-13 03:33:32 +01:00
}
2010-12-29 22:07:17 +01:00
def sort ( cMap : CompiledMap ) : Seq [ Compiled ] =
Dag . topologicalSort ( cMap . values ) ( _ . dependencies . map ( cMap ) )
def compile ( sMap : ScopedMap ) : CompiledMap =
sMap . toSeq . map { case ( k , ss ) =>
2011-02-16 00:43:44 +01:00
val deps = ss flatMap { _ . dependsOn } toSet ;
2010-12-29 22:07:17 +01:00
val eval = ( settings : Settings [ Scope ] ) => ( settings /: ss ) ( applySetting )
2011-02-16 00:43:44 +01:00
( k , new Compiled ( k , deps , eval ) )
2010-12-13 03:33:32 +01:00
} toMap ;
2010-12-29 22:07:17 +01:00
def grouped ( init : Seq [ Setting [ _ ] ] ) : ScopedMap =
( ( IMap . empty : ScopedMap ) /: init ) ( ( m , s ) => add ( m , s ) )
def add [ T ] ( m : ScopedMap , s : Setting [ T ] ) : ScopedMap =
m . mapValue [ T ] ( s . key , Nil , ss => append ( ss , s ) )
def append [ T ] ( ss : Seq [ Setting [ T ] ] , s : Setting [ T ] ) : Seq [ Setting [ T ] ] =
if ( s . definitive ) s : : Nil else ss :+ s
2011-02-06 03:39:34 +01:00
2011-02-12 02:22:17 +01:00
def addLocal ( init : Seq [ Setting [ _ ] ] ) ( implicit scopeLocal : ScopeLocal ) : Seq [ Setting [ _ ] ] =
2011-02-06 03:39:34 +01:00
init . flatMap ( _ . dependsOn flatMap scopeLocal ) ++ init
2010-12-29 22:07:17 +01:00
2011-01-19 00:24:11 +01:00
def delegate ( sMap : ScopedMap ) ( implicit delegates : Scope => Seq [ Scope ] ) : ScopedMap =
2010-12-13 03:33:32 +01:00
{
2011-07-26 03:59:22 +02:00
def refMap ( refKey : ScopedKey [ _ ] , isFirst : Boolean ) = new ValidateRef { def apply [ T ] ( k : ScopedKey [ T ] ) =
2011-02-16 00:43:44 +01:00
delegateForKey ( sMap , k , delegates ( k . scope ) , refKey , isFirst )
2011-01-26 04:14:02 +01:00
}
2011-07-26 03:59:22 +02:00
val undefineds = new collection . mutable . ListBuffer [ Undefined ]
2011-01-26 04:14:02 +01:00
val f = new ( SettingSeq ~> SettingSeq ) { def apply [ T ] ( ks : Seq [ Setting [ T ] ] ) =
2011-07-26 03:59:22 +02:00
ks . zipWithIndex . map { case ( s , i ) =>
( s validateReferenced refMap ( s . key , i == 0 ) ) match {
case Right ( v ) => v
case Left ( l ) => undefineds ++= l ; s
}
}
2011-01-26 04:14:02 +01:00
}
2011-07-26 03:59:22 +02:00
val result = sMap mapValues f
if ( undefineds . isEmpty ) result else throw Uninitialized ( undefineds . toList )
2010-12-13 03:33:32 +01:00
}
2011-07-26 03:59:22 +02:00
private [ this ] def delegateForKey [ T ] ( sMap : ScopedMap , k : ScopedKey [ T ] , scopes : Seq [ Scope ] , refKey : ScopedKey [ _ ] , isFirst : Boolean ) : Either [ Undefined , ScopedKey [ T ] ] =
2010-12-29 22:07:17 +01:00
{
2011-07-26 03:59:22 +02:00
def resolve ( search : Seq [ Scope ] ) : Either [ Undefined , ScopedKey [ T ] ] =
2010-12-29 22:07:17 +01:00
search match {
2011-07-26 03:59:22 +02:00
case Seq ( ) => Left ( Undefined ( refKey , k ) )
2010-12-29 22:07:17 +01:00
case Seq ( x , xs @ _ * ) =>
val sk = ScopedKey ( x , k . key )
2011-04-28 02:40:52 +02:00
val definesKey = ( refKey != sk || ! isFirst ) && ( sMap contains sk )
2011-07-26 03:59:22 +02:00
if ( definesKey ) Right ( sk ) else resolve ( xs )
2010-12-29 22:07:17 +01:00
}
resolve ( scopes )
2010-12-13 03:33:32 +01:00
}
2010-12-29 22:07:17 +01:00
2011-01-19 00:24:11 +01:00
private [ this ] def applyInits ( ordered : Seq [ Compiled ] ) ( implicit delegates : Scope => Seq [ Scope ] ) : Settings [ Scope ] =
2010-12-29 22:07:17 +01:00
( empty /: ordered ) { ( m , comp ) => comp . eval ( m ) }
2010-12-13 03:33:32 +01:00
2011-01-19 00:24:11 +01:00
private [ this ] def applySetting [ T ] ( map : Settings [ Scope ] , setting : Setting [ T ] ) : Settings [ Scope ] =
{
2011-02-12 02:22:17 +01:00
val value = setting . init . get ( map )
val key = setting . key
map . set ( key . scope , key . key , value )
2011-01-19 00:24:11 +01:00
}
2010-12-13 03:33:32 +01:00
2011-07-26 03:59:22 +02:00
final class Uninitialized ( val undefined : Seq [ Undefined ] , msg : String ) extends Exception ( msg )
final class Undefined ( val definingKey : ScopedKey [ _ ] , val referencedKey : ScopedKey [ _ ] )
def Undefined ( definingKey : ScopedKey [ _ ] , referencedKey : ScopedKey [ _ ] ) : Undefined = new Undefined ( definingKey , referencedKey )
def Uninitialized ( keys : Seq [ Undefined ] ) : Uninitialized =
{
assert ( ! keys . isEmpty )
val keyStrings = keys map { u => display ( u . referencedKey ) + " from " + display ( u . definingKey ) }
val suffix = if ( keyStrings . length > 1 ) "s" else ""
val keysString = keyStrings . mkString ( "\n\t" , "\n\t" , "" )
new Uninitialized ( keys , "Reference" + suffix + " to undefined setting" + suffix + ": " + keysString )
}
2011-02-16 00:43:44 +01:00
final class Compiled ( val key : ScopedKey [ _ ] , val dependencies : Iterable [ ScopedKey [ _ ] ] , val eval : Settings [ Scope ] => Settings [ Scope ] )
2011-04-14 01:04:53 +02:00
{
override def toString = display ( key )
}
2010-12-29 22:07:17 +01:00
2011-02-12 02:22:17 +01:00
sealed trait Initialize [ T ]
2010-12-13 03:33:32 +01:00
{
2010-12-29 22:07:17 +01:00
def dependsOn : Seq [ ScopedKey [ _ ] ]
2011-02-12 02:22:17 +01:00
def map [ S ] ( g : T => S ) : Initialize [ S ]
def mapReferenced ( g : MapScoped ) : Initialize [ T ]
2011-07-26 03:59:22 +02:00
def validateReferenced ( g : ValidateRef ) : Either [ Seq [ Undefined ] , Initialize [ T ] ]
2011-02-12 02:22:17 +01:00
def zip [ S ] ( o : Initialize [ S ] ) : Initialize [ ( T ,S ) ] = zipWith ( o ) ( ( x , y ) => ( x , y ) )
def zipWith [ S ,U ] ( o : Initialize [ S ] ) ( f : ( T , S ) => U ) : Initialize [ U ] = new Joined [ T ,S ,U ] ( this , o , f )
2011-07-20 03:29:05 +02:00
def mapConstant ( g : MapConstant ) : Initialize [ T ]
2011-02-12 02:22:17 +01:00
def get ( map : Settings [ Scope ] ) : T
}
2011-03-01 14:48:14 +01:00
object Initialize
{
implicit def joinInitialize [ T ] ( s : Seq [ Initialize [ T ] ] ) : JoinInitSeq [ T ] = new JoinInitSeq ( s )
final class JoinInitSeq [ T ] ( s : Seq [ Initialize [ T ] ] )
{
def join [ S ] ( f : Seq [ T ] => S ) : Initialize [ S ] = this . join map f
def join : Initialize [ Seq [ T ] ] = Initialize . join ( s )
}
def join [ T ] ( inits : Seq [ Initialize [ T ] ] ) : Initialize [ Seq [ T ] ] =
inits match
{
case Seq ( ) => value ( Nil )
case Seq ( x , xs @ _ * ) => ( join ( xs ) zipWith x ) ( ( t , h ) => h +: t )
}
}
2011-04-14 01:09:33 +02:00
sealed trait SettingsDefinition {
def settings : Seq [ Setting [ _ ] ]
}
final class SettingList ( val settings : Seq [ Setting [ _ ] ] ) extends SettingsDefinition
final class Setting [ T ] ( val key : ScopedKey [ T ] , val init : Initialize [ T ] ) extends SettingsDefinition
2011-02-12 02:22:17 +01:00
{
2011-04-14 01:09:33 +02:00
def settings = this : : Nil
2011-02-12 02:22:17 +01:00
def definitive : Boolean = ! init . dependsOn . contains ( key )
def dependsOn : Seq [ ScopedKey [ _ ] ] = remove ( init . dependsOn , key )
def mapReferenced ( g : MapScoped ) : Setting [ T ] = new Setting ( key , init mapReferenced g )
2011-07-26 03:59:22 +02:00
def validateReferenced ( g : ValidateRef ) : Either [ Seq [ Undefined ] , Setting [ T ] ] = ( init validateReferenced g ) . right . map ( newI => new Setting ( key , newI ) )
2011-02-12 02:22:17 +01:00
def mapKey ( g : MapScoped ) : Setting [ T ] = new Setting ( g ( key ) , init )
2011-03-21 03:54:01 +01:00
def mapInit ( f : ( ScopedKey [ T ] , T ) => T ) : Setting [ T ] = new Setting ( key , init . map ( t => f ( key , t ) ) )
2011-07-20 03:29:05 +02:00
def mapConstant ( g : MapConstant ) : Setting [ T ] = new Setting ( key , init mapConstant g )
2011-02-16 00:43:44 +01:00
override def toString = "setting(" + key + ")"
2011-02-12 02:22:17 +01:00
}
2011-05-08 04:02:06 +02:00
private [ this ] final class Optional [ S ,T ] ( a : Option [ ScopedKey [ S ] ] , f : Option [ S ] => T ) extends Initialize [ T ]
{
def dependsOn = a . toList
def map [ Z ] ( g : T => Z ) : Initialize [ Z ] = new Optional [ S ,Z ] ( a , g compose f )
def get ( map : Settings [ Scope ] ) : T = f ( a map asFunction ( map ) )
2011-07-26 03:59:22 +02:00
def mapReferenced ( g : MapScoped ) = new Optional ( a map g . fn , f )
def validateReferenced ( g : ValidateRef ) = Right ( new Optional ( a flatMap { sk => g ( sk ) . right . toOption } , f ) )
2011-07-20 03:29:05 +02:00
def mapConstant ( g : MapConstant ) : Initialize [ T ] =
( a flatMap g . fn ) match {
case None => this
case s => new Value ( ( ) => f ( s ) )
}
2011-05-08 04:02:06 +02:00
}
2011-02-12 02:22:17 +01:00
private [ this ] final class Joined [ S ,T ,U ] ( a : Initialize [ S ] , b : Initialize [ T ] , f : ( S , T ) => U ) extends Initialize [ U ]
{
def dependsOn = a . dependsOn ++ b . dependsOn
def mapReferenced ( g : MapScoped ) = new Joined ( a mapReferenced g , b mapReferenced g , f )
2011-07-26 03:59:22 +02:00
def validateReferenced ( g : ValidateRef ) =
( a validateReferenced g , b validateReferenced g ) match {
case ( Right ( ak ) , Right ( bk ) ) => Right ( new Joined ( ak , bk , f ) )
case ( au , bu ) => Left ( ( au . left . toSeq ++ bu . left . toSeq ) . flatten )
}
2011-02-12 02:22:17 +01:00
def map [ Z ] ( g : U => Z ) = new Joined [ S ,T ,Z ] ( a , b , ( s , t ) => g ( f ( s , t ) ) )
2011-07-20 03:29:05 +02:00
def mapConstant ( g : MapConstant ) = new Joined [ S ,T ,U ] ( a mapConstant g , b mapConstant g , f )
2011-02-12 02:22:17 +01:00
def get ( map : Settings [ Scope ] ) : U = f ( a get map , b get map )
2010-12-13 03:33:32 +01:00
}
2011-02-12 02:22:17 +01:00
private [ this ] final class Value [ T ] ( value : ( ) => T ) extends Initialize [ T ]
2010-12-13 03:33:32 +01:00
{
2010-12-29 22:07:17 +01:00
def dependsOn = Nil
2011-01-19 00:24:11 +01:00
def mapReferenced ( g : MapScoped ) = this
2011-07-26 03:59:22 +02:00
def validateReferenced ( g : ValidateRef ) = Right ( this )
2011-02-12 02:22:17 +01:00
def map [ S ] ( g : T => S ) = new Value [ S ] ( ( ) => g ( value ( ) ) )
2011-07-20 03:29:05 +02:00
def mapConstant ( g : MapConstant ) = this
2011-02-12 02:22:17 +01:00
def get ( map : Settings [ Scope ] ) : T = value ( )
2010-09-08 20:29:00 +02:00
}
2011-02-12 02:22:17 +01:00
private [ this ] final class Apply [ HL <: HList , T ] ( val f : HL => T , val inputs : KList [ ScopedKey , HL ] ) extends Initialize [ T ]
2010-12-13 03:33:32 +01:00
{
2011-02-12 02:22:17 +01:00
def dependsOn = inputs . toList
def mapReferenced ( g : MapScoped ) = new Apply ( f , inputs transform g )
def map [ S ] ( g : T => S ) = new Apply ( g compose f , inputs )
2011-07-20 03:29:05 +02:00
def mapConstant ( g : MapConstant ) = Reduced . reduceH ( inputs , g ) . combine ( ( keys , expand ) => new Apply ( f compose expand , keys ) )
2011-02-12 02:22:17 +01:00
def get ( map : Settings [ Scope ] ) = f ( inputs down asTransform ( map ) )
2011-07-26 03:59:22 +02:00
def validateReferenced ( g : ValidateRef ) =
{
val tx = inputs . transform ( g )
val undefs = tx . toList . flatMap ( _ . left . toSeq )
val get = new ( ValidatedRef ~> ScopedKey ) { def apply [ T ] ( vr : ValidatedRef [ T ] ) = vr . right . get }
if ( undefs . isEmpty ) Right ( new Apply ( f , tx transform get ) ) else Left ( undefs )
}
2011-01-19 00:24:11 +01:00
}
2011-07-26 03:59:22 +02:00
2011-02-12 02:22:17 +01:00
private [ this ] final class KApply [ HL <: HList , M [ _ ] , T ] ( val f : KList [ M , HL ] => T , val inputs : KList [ ( { type l [ t ] = ScopedKey [ M [ t ] ] } ) # l , HL ] ) extends Initialize [ T ]
2011-01-19 00:24:11 +01:00
{
2011-07-26 03:59:22 +02:00
type ScopedKeyM [ T ] = ScopedKey [ M [ T ] ]
type VRefM [ T ] = ValidatedRef [ M [ T ] ]
2011-02-12 02:22:17 +01:00
def dependsOn = unnest ( inputs . toList )
def mapReferenced ( g : MapScoped ) = new KApply [ HL , M , T ] ( f , inputs . transform [ ( { type l [ t ] = ScopedKey [ M [ t ] ] } ) # l ] ( nestCon ( g ) ) )
def map [ S ] ( g : T => S ) = new KApply [ HL , M , S ] ( g compose f , inputs )
def get ( map : Settings [ Scope ] ) = f ( inputs . transform [ M ] ( nestCon [ ScopedKey , Id , M ] ( asTransform ( map ) ) ) )
2011-07-20 03:29:05 +02:00
def mapConstant ( g : MapConstant ) =
{
2011-07-26 03:59:22 +02:00
def mk [ HLk <: HList ] ( keys : KList [ ScopedKeyM , HLk ] , expand : KList [ M , HLk ] => KList [ M , HL ] ) = new KApply [ HLk , M , T ] ( f compose expand , keys )
2011-07-20 03:29:05 +02:00
Reduced . reduceK [ HL , ScopedKey , M ] ( inputs , nestCon ( g ) ) combine mk
}
2011-07-26 03:59:22 +02:00
def validateReferenced ( g : ValidateRef ) =
{
val tx = inputs . transform [ VRefM ] ( nestCon ( g ) )
val undefs = tx . toList . flatMap ( _ . left . toSeq )
val get = new ( VRefM ~> ScopedKeyM ) { def apply [ T ] ( vr : ValidatedRef [ M [ T ] ] ) = vr . right . get }
if ( undefs . isEmpty )
Right ( new KApply [ HL , M , T ] ( f , tx . transform ( get ) ) )
else
Left ( undefs )
}
2011-01-19 00:24:11 +01:00
private [ this ] def unnest ( l : List [ ScopedKey [ M [ T ] ] forSome { type T } ] ) : List [ ScopedKey [ _ ] ] = l . asInstanceOf [ List [ ScopedKey [ _ ] ] ]
}
2011-02-12 02:22:17 +01:00
private [ this ] final class Uniform [ S , T ] ( val f : Seq [ S ] => T , val inputs : Seq [ ScopedKey [ S ] ] ) extends Initialize [ T ]
2011-01-19 00:24:11 +01:00
{
2011-02-12 02:22:17 +01:00
def dependsOn = inputs
def mapReferenced ( g : MapScoped ) = new Uniform ( f , inputs map g . fn [ S ] )
2011-07-26 03:59:22 +02:00
def validateReferenced ( g : ValidateRef ) =
{
val ( undefs , ok ) = List . separate ( inputs map g . fn [ S ] )
if ( undefs . isEmpty ) Right ( new Uniform ( f , ok ) ) else Left ( undefs )
}
2011-02-12 02:22:17 +01:00
def map [ S ] ( g : T => S ) = new Uniform ( g compose f , inputs )
2011-07-20 03:29:05 +02:00
def mapConstant ( g : MapConstant ) =
{
val red = Reduced . reduceSeq ( inputs , g )
new Uniform ( f compose red . expand , red . keys )
}
2011-02-12 02:22:17 +01:00
def get ( map : Settings [ Scope ] ) = f ( inputs map asFunction ( map ) )
2010-12-13 03:33:32 +01:00
}
2011-01-19 00:24:11 +01:00
private def remove [ T ] ( s : Seq [ T ] , v : T ) = s filterNot ( _ == v )
2010-12-13 03:33:32 +01:00
}