예제 #1
0
 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);
             }
         }
     }
 }
예제 #2
0
        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;
            }
        }
예제 #3
0
 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));
             }
         }
     }
 }
예제 #4
0
        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);
                }
            }
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
            }
        }
예제 #7
0
        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);
                }
            }
        }
예제 #8
0
        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));
        }
예제 #9
0
        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);
        }
예제 #10
0
 public GenericTypeMapper(GeneratorTypeReplacer replacer)
 {
     _replacer = replacer;
 }