private static void CheckTypeForGenericParams( IType type, HashSet <string> genericsSet, BooClassBuilder builder, GeneratorTypeReplacer mapper) { if (type is IGenericParameter) { if (!genericsSet.Contains(type.Name)) { builder.AddGenericParameter(type.Name); genericsSet.Add(type.Name); } if (!mapper.ContainsType(type)) { mapper.Replace( type, (IType)builder.ClassDefinition.GenericParameters .First(gp => gp.Name.Equals(type.Name)).Entity); } } else { var genType = type as IConstructedTypeInfo; if (genType != null) { foreach (var arg in genType.GenericArguments) { CheckTypeForGenericParams(arg, genericsSet, builder, mapper); } } } }
private void CreateSharedLocalsClass() { _shared.Clear(); CollectSharedLocalEntities(_currentMethod.Locals); CollectSharedLocalEntities(_currentMethod.Parameters); if (_shared.Count > 0) { BooClassBuilder builder = CodeBuilder.CreateClass(Context.GetUniqueName(_currentMethod.Name, "locals")); builder.Modifiers |= TypeMemberModifiers.Internal; builder.AddBaseType(TypeSystemServices.ObjectType); var genericsSet = new HashSet <string>(); var replacer = new GeneratorTypeReplacer(); foreach (ILocalEntity local in _shared) { CheckTypeForGenericParams(local.Type, genericsSet, builder, replacer); Field field = builder.AddInternalField( string.Format("${0}", local.Name), replacer.MapType(local.Type)); _mappings[local] = (IField)field.Entity; } builder.AddConstructor().Body.Add( CodeBuilder.CreateSuperConstructorInvocation(TypeSystemServices.ObjectType)); _sharedLocalsClass = builder.ClassDefinition; } }
private static void CheckMethodGenerics(Method call, ClassDefinition node) { if (node.GenericParameters.Count > 0) { var tf = new GenericTypeFinder(); call.Body.Accept(tf); var results = tf.Results.ToArray(); if (results.Length > 0) { var replacer = new GeneratorTypeReplacer(); foreach (var gtype in results) { var replacement = node.GenericParameters.FirstOrDefault(gp => gp.Name == gtype.Name); if (replacement != null) { replacer.Replace(gtype, (IType)replacement.Entity); } } if (replacer.Any) { call.Body.Accept(new GenericTypeMapper(replacer)); } } } }
public override void LeaveBlockExpression(BlockExpression node) { var closureEntity = GetEntity(node) as InternalMethod; if (closureEntity == null) { return; } var collector = new ForeignReferenceCollector(); { collector.CurrentMethod = closureEntity.Method; collector.CurrentType = closureEntity.DeclaringType; closureEntity.Method.Body.Accept(collector); if (collector.ContainsForeignLocalReferences) { BooClassBuilder closureClass = CreateClosureClass(collector, closureEntity); if (closureEntity is InternalGenericMethod) { closureEntity = GetEntity(closureEntity.Method) as InternalMethod; } closureClass.ClassDefinition.LexicalInfo = node.LexicalInfo; collector.AdjustReferences(); if (_mapper != null) { closureClass.ClassDefinition.Accept(new GenericTypeMapper(_mapper)); } ReplaceCurrentNode( CodeBuilder.CreateMemberReference( collector.CreateConstructorInvocationWithReferencedEntities( closureClass.Entity, node.GetAncestor <Method>()), closureEntity)); } else { _mapper = closureEntity.Method["GenericMapper"] as GeneratorTypeReplacer; if (_mapper != null) { closureEntity.Method.Accept(new GenericTypeMapper(_mapper)); } IMethod entity = closureEntity; if (entity.GenericInfo != null) { entity = MapGenericMethod(entity, node.GetAncestor <Method>().GenericParameters); } Expression expression = CodeBuilder.CreateMemberReference(entity); expression.LexicalInfo = node.LexicalInfo; TypeSystemServices.GetConcreteExpressionType(expression); ReplaceCurrentNode(expression); } } }
public MethodInvocationExpression CreateConstructorInvocationWithReferencedEntities(IType type, Method containingMethod) { GeneratorTypeReplacer mapper; type = GeneratorTypeReplacer.MapTypeInMethodContext(type, containingMethod, out mapper); MethodInvocationExpression mie = CodeBuilder.CreateConstructorInvocation(type.GetConstructors().First()); foreach (var entity in _referencedEntities.Keys) { mie.Arguments.Add(CreateForeignReference(entity)); } if (mapper != null) { mie.Accept(new GenericTypeMapper(mapper)); } return(mie); }
private void Map() { var type = GeneratorTypeReplacer.MapTypeInMethodContext((IType)_sharedLocalsClass.Entity, _currentMethod); var conType = type as GenericConstructedType; if (conType != null) { foreach (var key in _mappings.Keys.ToArray()) { _mappings[key] = (IField)conType.ConstructedInfo.Map(_mappings[key]); } } var locals = CodeBuilder.DeclareLocal(_currentMethod, "$locals", type); foreach (var reference in _references) { IField mapped; if (!_mappings.TryGetValue(reference.Entity, out mapped)) { continue; } reference.ParentNode.Replace( reference, CodeBuilder.CreateMemberReference( CodeBuilder.CreateReference(locals), mapped)); } var initializationBlock = new Block(); initializationBlock.Add(CodeBuilder.CreateAssignment( CodeBuilder.CreateReference(locals), CodeBuilder.CreateConstructorInvocation(type.GetConstructors().First()))); InitializeSharedParameters(initializationBlock, locals); _currentMethod.Body.Statements.Insert(0, initializationBlock); foreach (IEntity entity in _mappings.Keys) { _currentMethod.Locals.RemoveByEntity(entity); } }
private void MapGenerics(ClassDefinition cd) { var finder = new GenericTypeFinder(); foreach (var member in cd.Members) { member.Accept(finder); } _mapper = _mapper ?? new GeneratorTypeReplacer(); var genParams = cd.GenericParameters; foreach (var genType in finder.Results) { var replacement = genParams.FirstOrDefault(p => p.Name.Equals(genType.Name)); if (replacement != null && genType != replacement.Entity) { _mapper.Replace(genType, (IType)replacement.Entity); } } }
private static IMethod RemapMethod(Node node, GenericMappedMethod gmm, IType[] genParams) { var sourceMethod = gmm.SourceMember; if (sourceMethod.GenericInfo != null) { throw new CompilerError(node, "Mapping generic methods in generators is not implemented yet"); } var baseType = sourceMethod.DeclaringType; var genericInfo = baseType.GenericInfo; if (genericInfo == null) { throw new CompilerError(node, "Mapping generic nested types in generators is not implemented yet"); } var genericArgs = ((IGenericArgumentsProvider)gmm.DeclaringType).GenericArguments; var collector = new TypeCollector(type => type is IGenericParameter); foreach (var arg in genericArgs) { collector.Visit(arg); } var mapper = new GeneratorTypeReplacer(); foreach (var genParam in collector.Matches) { var mappedArg = genParams.SingleOrDefault(gp => gp.Name == genParam.Name); if (mappedArg != null) { mapper.Replace(genParam, mappedArg); } } var newType = (IConstructedTypeInfo) new GenericConstructedType( baseType, genericArgs.Select(mapper.MapType).ToArray()); return((IMethod)newType.Map(sourceMethod)); }
BooClassBuilder CreateClosureClass(ForeignReferenceCollector collector, InternalMethod closure) { Method method = closure.Method; TypeDefinition parent = method.DeclaringType; parent.Members.Remove(method); _mapper = method["GenericMapper"] as GeneratorTypeReplacer; BooClassBuilder builder = collector.CreateSkeletonClass(closure.Name, method.LexicalInfo); parent.Members.Add(builder.ClassDefinition); builder.ClassDefinition.Members.Add(method); method.Name = "Invoke"; if (method.IsStatic) { // need to adjust paremeter indexes (parameter 0 is now self) foreach (ParameterDeclaration parameter in method.Parameters) { ((InternalParameter)parameter.Entity).Index += 1; } } method.Modifiers = TypeMemberModifiers.Public; var coll = new GenericTypeCollector(CodeBuilder); coll.Process(builder.ClassDefinition); if (!method.GenericParameters.IsEmpty) { MapMethodGenerics(builder, method); } if (builder.ClassDefinition.GenericParameters.Count > 0) { MapGenerics(builder.ClassDefinition); } return(builder); }
public GenericTypeMapper(GeneratorTypeReplacer replacer) { _replacer = replacer; }