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 { } } } }