Приве всем!
Пытаюсь построить generic-тип с произвольным количеством параметров. В метод передаётся сколько должно быть типов по значению и сколько по ссылке.
Вопрос в том, как сгенерировать ограничения where для заранее неизвестного количества типов.
public BuildKeyClass( byRefCount : int, byValCount : int ) : void
{
def refTypeNames = $[$"U$i" | i in $[1..byRefCount]];
def valTypeNames = $[$"V$i" | i in $[1..byValCount]];
def typeNames = refTypeNames.Append( valTypeNames );
def types = typeNames.Map(id => <[ $(id : usesite) ]>);
def typeParams = types.Map( n => { | <[$(n : name)]> => PT.Splicable.Name( n ) } );
/*
def getHead( _ )
{
| head :: _ => head;
}
def tp = getHead( typeParams ); // Так можно получить только заранее известное количество типов
*/
def env = workingContext_s.Env;
def builder = env.Define(
<[decl:
public class $(className : dyn) [..$typeParams]
// where $tp : struct // Это работает, но только для заранее известного количества типов
{
}
]> );
builder.Compile();
}
Хочется получить в выделенной жирным строке что-то вроде
where U1 : struct
where U2 : struct
where U3 : struct
where V1 : class
where V2 : class
Как это сделать?
Спасибо.
Пока удалось только полухаком через AST. Может кто знает как это псевдоцитированием заменить?
public BuildKeyClass( byRefCount : int, byValCount : int, byRefAuto : int = 0, byValAuto : int = 0 ) : TypeBuilder
{
def buildName = seed => $"$(seed)_R$(byRefCount)A$(byRefAuto)V$(byValCount)A$(byValAuto)";
def className : string = buildName( "Key" );
def makeName = str => <[ $(str : usesite) ]>;
def makeTypeParams = _.Map( n => { | <[$(n : name)]> => PT.Splicable.Name( n ) } );
def makeConstraints = ( lst, name ) => lst.Map( PT.Constraint( _, makeName( name ) ) );
def refTypeNames = $[$"U$i" | i in $[1..byRefCount]];
def valTypeNames = $[$"V$i" | i in $[1..byValCount]];
def refTypes = refTypeNames.Map( makeName );
def valTypes = valTypeNames.Map( makeName );
// Generic class stuff
def refTypeParams = makeTypeParams( refTypes );
def valTypeParams = makeTypeParams( valTypes );
def refConstraints = makeConstraints( refTypeParams, "class" );
def valConstraints = makeConstraints( valTypeParams, "struct" );
def typeParams = refTypeParams + valTypeParams;
def constraints = refConstraints + valConstraints;
def root = <[decl:
public class $(className : usesite) // [..$typeParams ] // It's not necessary any more.
{
}
]>;
root.td.typarms = PT.Typarms( typeParams, constraints );
// Declare class skeleton
def env = workingContext_s.Env;
def builder = env.Define( root );
def defineMembers = _.Iter( f => builder.Define( f ) );
// Declare fields
def refFieldNames = $[1..byRefCount].Map( i => $"key$(i)_" );
def valFieldNames = $[1..byValCount].Map( i => $"key$(i + byRefCount)_" );
def refFields = List.Combine( refTypes, refFieldNames ).Map(
( typ, fld ) => <[ decl: private mutable $(fld : usesite) : $typ = null; ]> );
def valFields = List.Combine( valTypes, valFieldNames ).Map(
( typ, fld ) => <[ decl: private mutable $(fld : usesite) : $typ ]> );
defineMembers( refFields );
defineMembers( valFields );
// Declare properties
def refPropNames = $[1..byRefCount].Map( i => $"Key$(i)" );
def valPropNames = $[1..byValCount].Map( i => $"Key$(i + byRefCount)" );
def refProps = List.Combine( refTypes, List.Combine( refFieldNames, refPropNames ) ).Map(
fun( _ )
{ | ( typ, ( fld, prop ) ) =>
<[decl:
public $(prop : usesite) : $typ
{
get
{
$(fld : usesite);
}
set
{
$(fld : usesite) = value;
}
}
]>
} );
def valProps = List.Combine( valTypes, List.Combine( valFieldNames, valPropNames ) ).Map(
fun( _ )
{ | ( typ, ( fld, prop ) ) =>
<[decl:
public $(prop : usesite) : $typ
{
get
{
$(fld : usesite);
}
set
{
$(fld : usesite) = value;
}
}
]>
} );
defineMembers( refProps );
defineMembers( valProps );
builder.Compile();
builder;
}
Здравствуйте, SergASh, Вы писали:
SAS>Пытаюсь построить generic-тип с произвольным количеством параметров. В метод передаётся сколько должно быть типов по значению и сколько по ссылке.
SAS>Вопрос в том, как сгенерировать ограничения where для заранее неизвестного количества типов.
SAS>SAS> <[decl:
SAS> public class $(className : dyn) [..$typeParams]
SAS> // where $tp : struct // Это работает, но только для заранее известного количества типов
SAS>
SAS>Хочется получить в выделенной жирным строке что-то вроде
SAS>SAS> where U1 : struct
SAS> where U2 : struct
SAS> where U3 : struct
SAS> where V1 : class
SAS> where V2 : class
SAS>
SAS>Как это сделать?
Думаю, так:
...
def builder = env.Define(
<[decl:
public class $(className : dyn) where ..$constraints
...
Естественно в constraints должны быть список специально подготовленных для констрэйнов.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Здравствуйте, SergASh, Вы писали:
SAS>А сами ограничения псевдоцитированием можно построить, или только явно через Parsetree.Constraint ?
Я это не выяснял. Скорее всего органичения исходно записываются в виде выражения, а это значит, что можно. Но не факт.
... << RSDN@Home 1.2.0 alpha rev. 637>>