コード例 #1
0
        private void BuildCullAmbiguities(ParserCompiler compiler, ParserBuilder parserBuilder, IIntermediateCliManager identityManager)
        {
            bool lexicallyAmbiguousModel = compiler._GrammarSymbols.AmbiguousSymbols.Count() > 0;

            if (!lexicallyAmbiguousModel)
            {
                return;
            }
            var runningAmbiguities = this._cullAmbiguities.Locals.Add(
                new TypedName("runningAmbiguities", compiler.LexicalSymbolModel.ValidSymbols), new DefaultValueExpression(compiler.LexicalSymbolModel.ValidSymbols));
            var resultAmbiguities = this._cullAmbiguities.Locals.Add(
                new TypedName("resultAmbiguities", compiler.LexicalSymbolModel.ValidSymbols), new DefaultValueExpression(compiler.LexicalSymbolModel.ValidSymbols));
            var unambiguousSource = this._cullAmbiguities.Parameters["unambiguousSource"];

            this._cullAmbiguities.Comment("Remove the ambiguities that are currently present, a larger multiple-symbol ambiguity may trump what was there due to the follow-union.");
            this._cullAmbiguities.Assign((IMemberReferenceExpression)unambiguousSource.GetReference(), AssignmentOperation.BitwiseExclusiveOrAssign, unambiguousSource.GetReference().BitwiseAnd(_AllAmbiguitiesField.GetReference()));
            bool first = true;

            foreach (var ambiguity in compiler._GrammarSymbols.AmbiguousSymbols)
            {
                var ambiguityDetail          = compiler.AmbiguityDetail[ambiguity];
                IBlockStatementParent target = this._cullAmbiguities;
                if (first)
                {
                    first = false;
                }
                else
                {
                    target = target.If(runningAmbiguities.GetReference().BitwiseAnd(ambiguityDetail.AmbiguityKeyReference.GetReference()).InequalTo(ambiguityDetail.AmbiguityKeyReference.GetReference()));
                }
                var assignmentCheck = target.If(unambiguousSource.BitwiseAnd(ambiguityDetail.AmbiguityKeyReference).EqualTo(ambiguityDetail.AmbiguityKeyReference));
                assignmentCheck.Assign(runningAmbiguities.GetReference(), AssignmentOperation.BitwiseOrAssign, ambiguityDetail.AmbiguityKeyReference.GetReference());
                assignmentCheck.Assign(resultAmbiguities.GetReference(), AssignmentOperation.BitwiseOrAssign, ambiguityDetail.AmbiguityReference.GetReference());
            }
            _cullAmbiguities.Return(resultAmbiguities.GetReference());
        }
        public void BuildImplementation(IAssembly target)
        {
            if (IEnumerableOfT == null)
            {
                IEnumerableOfT = typeof(IEnumerable <>).GetTypeReference <IInterfaceType>(this._assembly.IdentityManager);
            }
            if (IControlledDictionaryOfTKeyTValue == null)
            {
                IControlledDictionaryOfTKeyTValue = typeof(IControlledDictionary <,>).GetTypeReference <IInterfaceType>(this._assembly.IdentityManager);
            }
            if (IntermediateDeclDict == null)
            {
                IntermediateDeclDict = typeof(IIntermediateDeclarationDictionary <, ,>).GetTypeReference <IInterfaceType>(this._assembly.IdentityManager);
            }
            IType ignoreAttr    = typeof(VisitorImplementationIgnorePropertyAttribute).GetTypeReference(this._assembly.IdentityManager);
            IType ignoreSetAttr = typeof(VisitorImplementationIgnoreLocalSetAttribute).GetTypeReference(this._assembly.IdentityManager);
            var   requireAttr   = typeof(VisitorPropertyRequirementAttribute).GetTypeReference(this._assembly.IdentityManager);
            bool  visitorsDoNotNeedConstraints = !string.IsNullOrEmpty(this.Detail.VisitRefactorName);
            var   builderInterfaces            = this._builders.SelectMany(k => k.RelevantTypes).Distinct().OfType <IInterfaceType>().ToArray();
            //var allEnumerables = builderInterfaces.Select(k => CreateEnumerableVariant(k)).ToArray();
            var distinctInterfaces =
                builderInterfaces.Concat(builderInterfaces.SelectMany(k => k.ImplementedInterfaces)).Distinct().ToArray();
            var interfaceProperties =
                (from iFace in distinctInterfaces.OfType <IInterfaceType>()
                 from prop in iFace.Properties.Values /*.Where(k => IsPropertyRelevant(ignoreAttr, builderInterfaces, k))*/.DefaultIfEmpty()
                 group prop by iFace).ToDictionary(k => k.Key, v => (v.First() == null ? (IEnumerable <IInterfacePropertyMember>) new IInterfacePropertyMember[0] : v).ToList());
            var interfacesWithAccept       = distinctInterfaces.OfType <IInterfaceType>().Where(k => k.Methods.Values.Any(j => j.Name == "Accept")).ToArray();
            var actionDetail               = typeof(VisitorImplementationActionDetailAttribute).GetTypeReference <IClassType>(this._assembly.IdentityManager);
            var relevantActionDetail       = target.Metadata.Where(k => k.Type == actionDetail && k.Parameters.GetIndexedParameter <string>(0).Item2 == this.Detail.TargetContext);
            var relevantActionDetailLookup = relevantActionDetail.ToDictionary(k => k.Parameters.GetIndexedParameter <IType>(1).Item2, v => VisitorImplementationActionDetail.DeriveFromMetadata(v));
            var relevantActionTypes        = relevantActionDetailLookup.Keys.ToArray();

            //foreach (var key in relevantActionTypes)
            //    foreach (var @interface in key.ImplementedInterfaces)
            //        if (!relevantActionDetailLookup.ContainsKey(@interface))
            //            relevantActionDetailLookup.Add(@interface, relevantActionDetailLookup[key]);
            builderInterfaces = builderInterfaces.Concat(interfacesWithAccept).Distinct().ToArray();
            var inheritanceDetail = (from iFace in builderInterfaces
                                     let baseTypes = iFace.ImplementedInterfaces.OfType <IInterfaceType>()
                                                     from iFace2 in new[] { iFace }.Concat(baseTypes).Distinct()
                                     group iFace2 by iFace).ToDictionary(k => k.Key, v => v.ToArray());

            bool isVoidReturn = !this.Detail.YieldingVisitor;

            if (visitorsDoNotNeedConstraints)
            {
                this.SecondaryResult = this.VisitorResult.Parts.Add();
                var relativeRoot = new string[] { this.VisitorResult.NamespaceName, this._assembly.DefaultNamespace.FullName }.GetRelativeRoot(".");
                if (!string.IsNullOrEmpty(relativeRoot))
                {
                    relativeRoot = this.VisitorResult.NamespaceName.Substring(relativeRoot.Length + 1);
                    relativeRoot = relativeRoot.Replace(".", @"\") + @"\";
                }

                this.SecondaryResult.Assembly.FileName = string.Format("{2}{0} ({1} Signatures)", this.Detail.TargetContext, this.Detail.VisitRefactorName, relativeRoot);
                this.VisitorResult.Assembly.FileName   = string.Format("{1}{0} (Visitor Signatures)", this.Detail.TargetContext, relativeRoot);
            }
            foreach (var builder in this._builders)
            {
                if (this.Detail.InheritedVisitors.Contains(builder.Detail.TargetContext))
                {
                    this.VisitorResult.ImplementedInterfaces.ImplementInterfaceQuick(builder.VisitorInterface);
                }
                foreach (var method in builder.VisitorInterface.Methods.Values)
                {
                    var gpData = new GenericParameterData[method.GenericParameters.Count];
                    if (method.TypeParameters.Count > 0)
                    {
                        for (int i = 0; i < method.TypeParameters.Count; i++)
                        {
                            var gParam = method.TypeParameters.Values[i];
                            gpData[i] = new GenericParameterData(gParam.Name);
                            if (!visitorsDoNotNeedConstraints)
                            {
                                gpData[i].Constraints.AddRange(gParam.Constraints.Select(k => k.TurnTypeParametersIntoSymbols()));
                                gpData[i].SpecialConstraint = gParam.SpecialConstraint;
                            }
                        }
                    }
                    var parameterData = new TypedNameSeries(method.Parameters.Values.Select(k => k.ParameterType.WithName(k.Name)));
                    var newMethod     = this.VisitorResult.Methods.Add(method.ReturnType.WithName(method.Name), parameterData, gpData);
                    if (visitorsDoNotNeedConstraints)
                    {
                        newMethod.Implementations.Add(builder.VisitorInterface);
                        foreach (var gpDetail in from gpDatum in gpData
                                 join genericParameter in method.TypeParameters.Values on gpDatum.Name equals genericParameter.Name
                                 select new { GenericParameterDatum = gpDatum, GenericParameter = genericParameter })
                        {
                            gpDetail.GenericParameterDatum.Constraints.AddRange(gpDetail.GenericParameter.Constraints.Select(k => k.TurnTypeParametersIntoSymbols()));
                            gpDetail.GenericParameterDatum.SpecialConstraint = gpDetail.GenericParameter.SpecialConstraint;
                        }
                        var secondNewMethod = this.SecondaryResult.Methods.Add(method.ReturnType.WithName(this.Detail.VisitRefactorName), parameterData, gpData);
                        secondNewMethod.AccessLevel = AccessLevelModifiers.Public;
                        if (this.Detail.VisitRefactorAbstract)
                        {
                            secondNewMethod.IsAbstract = true;
                        }
                        var paramRefs  = parameterData.Select(k => newMethod.Parameters[k.Name].GetReference()).ToArray();
                        var invocation = newMethod.IsGenericConstruct
                                         ? secondNewMethod.GetReference(null, newMethod.GenericParameters).Invoke(paramRefs)
                                         : secondNewMethod.GetReference(null).Invoke(paramRefs);
                        var firstParam     = newMethod.Parameters.Values[0];
                        var firstParamType = firstParam.ParameterType;
                        if (firstParamType is IInterfaceType)
                        {
                            foreach (var prop in EnumerateInterfaceProperties((IInterfaceType)firstParamType, ignoreAttr, inheritanceDetail, interfaceProperties))
                            {
                                var propertyRelevanceInfo        = IsPropertyRelevant(prop.Item1, builderInterfaces, ignoreAttr, relevantActionTypes);
                                var requirement                  = prop.Item1.Metadata[requireAttr];
                                IBlockStatementParent codeTarget = secondNewMethod;
                                if (propertyRelevanceInfo.Item2 != VisitorImplementationTypeRelevance.NotRelevant)
                                {
                                    if (requirement != null)
                                    {
                                        codeTarget = codeTarget.If(firstParam.GetReference().GetProperty(requirement.Parameters.GetIndexedParameter <string>(0).Item2));
                                    }
                                    else if (prop.Item1.PropertyType.Type == TypeKind.Interface || prop.Item1.PropertyType.Type == TypeKind.Class)
                                    {
                                        codeTarget = codeTarget.If(firstParam.GetReference().GetProperty(prop.Item1.Name).InequalTo(IntermediateGateway.NullValue));
                                    }
                                }
                                switch (propertyRelevanceInfo.Item2)
                                {
                                case VisitorImplementationTypeRelevance.AsItem:
                                    codeTarget.Call(firstParam.GetReference().GetProperty(prop.Item1.Name).GetMethod("Accept").Invoke(new IExpression[] { this.VisitorResult.GetThis() }.Concat(newMethod.Parameters.Values.Skip(1).Select(k => k.GetReference())).ToArray()));
                                    break;

                                case VisitorImplementationTypeRelevance.AsActionableItemSet:
                                    ProcessActionableSet(relevantActionDetailLookup, firstParam, prop, propertyRelevanceInfo, codeTarget, 0, null);
                                    break;

                                case VisitorImplementationTypeRelevance.AsActionableValueSet:
                                    ProcessActionableSet(relevantActionDetailLookup, firstParam, prop, propertyRelevanceInfo, codeTarget, 1, "Values");
                                    break;

                                case VisitorImplementationTypeRelevance.AsActionableDeclValueSet:
                                    ProcessActionableSet(relevantActionDetailLookup, firstParam, prop, propertyRelevanceInfo, codeTarget, 2, "Values");
                                    break;

                                case VisitorImplementationTypeRelevance.AsActionableItem:
                                    IType ratType = propertyRelevanceInfo.Item1;
                                    if (ratType.IsGenericTypeParameter)
                                    {
                                        var gpRat      = (IGenericParameter)(ratType);
                                        var interfaces = gpRat.Constraints.Concat(gpRat.Constraints.SelectMany(r => r.ImplementedInterfaces)).Distinct().ToArray();
                                        ratType = interfaces.FirstOrDefault(k => relevantActionDetailLookup.ContainsKey(k));
                                    }
                                    else if (!relevantActionDetailLookup.ContainsKey(ratType))
                                    {
                                        var interfaces = ratType.ImplementedInterfaces;
                                        ratType = interfaces.FirstOrDefault(k => relevantActionDetailLookup.ContainsKey(k));
                                    }
                                    var currentActionDetail = relevantActionDetailLookup[ratType];
                                    codeTarget.Call(
                                        this.VisitorResult
                                        .GetThis()
                                        .GetMethod(currentActionDetail.TargetAction)
                                        .Invoke(
                                            firstParam
                                            .GetReference()
                                            .GetProperty(prop.Item1.Name)));
                                    break;
                                //case VisitorImplementationTypeRelevance.AsActionableItemSet:
                                //    IType enumerableRatType = propertyRelevanceInfo.Item1;
                                //    var genericParam = ((IGenericType)(enumerableRatType)).GenericParameters.FirstOrDefault();
                                //    if (genericParam != null)
                                //    {
                                //        if (genericParam.IsGenericTypeParameter)
                                //        {
                                //            var gpRat = (IGenericParameter)(genericParam);
                                //            var interfaces = gpRat.Constraints.Concat(gpRat.Constraints.SelectMany(r => r.ImplementedInterfaces)).Distinct().ToArray();
                                //            genericParam = interfaces.FirstOrDefault(k => relevantActionDetailLookup.ContainsKey(k));
                                //        }
                                //        else if (!relevantActionDetailLookup.ContainsKey(genericParam))
                                //        {
                                //            var interfaces = genericParam.ImplementedInterfaces;
                                //            genericParam = interfaces.FirstOrDefault(k => relevantActionDetailLookup.ContainsKey(k));
                                //        }
                                //        var currentActionSetDetail = relevantActionDetailLookup[genericParam];
                                //        codeTarget.Call(this.VisitorResult.GetThis().GetMethod(currentActionSetDetail.TargetPluralAction).Invoke(firstParam.GetReference().GetProperty(prop.Item1.Name)));
                                //    }
                                //    break;

                                case VisitorImplementationTypeRelevance.AsValueSet:
                                case VisitorImplementationTypeRelevance.AsDeclValueSet:
                                    codeTarget.Call(this.VisitorResult.GetThis().GetMethod(this.Detail.VisitRefactorName ?? "Visit").Invoke(firstParam.GetReference().GetProperty(prop.Item1.Name).GetProperty("Values")));
                                    break;

                                case VisitorImplementationTypeRelevance.AsItemSet:
                                    codeTarget.Call(this.VisitorResult.GetThis().GetMethod(this.Detail.VisitRefactorName ?? "Visit").Invoke(firstParam.GetReference().GetProperty(prop.Item1.Name)));
                                    break;

                                default:
                                    break;
                                }
                            }
                            if (!firstParamType.Metadata.Contains(ignoreSetAttr))
                            {
                                var enAccess = IsTypeRelevantForEnumerableAccess(builderInterfaces, firstParamType, relevantActionTypes);
                                if (enAccess.Item2 == VisitorImplementationTypeRelevance.AsItemSet)
                                {
                                    secondNewMethod.Call(this.VisitorResult.GetThis().GetMethod(this.Detail.VisitRefactorName ?? "Visit").Invoke(firstParam.GetReference().Cast(enAccess.Item1)));
                                }
                            }
                        }
                        if (isVoidReturn)
                        {
                            newMethod.Call(invocation);
                        }
                        else
                        {
                            newMethod.Return(invocation);
                        }
                    }
                    else
                    {
                    }
                }
            }
        }