private void ParseTypeParameterConstraint(TypeNode t, TokenSet followers, TypeNodeList parameters){ Debug.Assert(this.currentToken == Token.Where); this.GetNextToken(); //Get parameter name Identifier parameterName = this.scanner.GetIdentifier(); this.SkipIdentifierOrNonReservedKeyword(); //Get corresponding parameter in parameter list TypeNode parameter = null; int n = parameters == null ? 0 : parameters.Count; int i = 0; while (i < n){ parameter = parameters[i]; if (parameter != null && parameter.Name != null && parameter.Name.UniqueIdKey == parameterName.UniqueIdKey) break; i++; } if (i >= n){ //TODO: complain about parameter name not being present parameter = new TypeParameter(); parameter.Name = parameterName; } this.Skip(Token.Colon); TypeParameter tpar = (TypeParameter)parameter; //TODO: check if parameter already has a constraint //Add constraints switch (this.currentToken){ case Token.Class: this.GetNextToken(); tpar.TypeParameterFlags = TypeParameterFlags.ReferenceTypeConstraint; skipComma: if (this.currentToken == Token.Comma){ this.GetNextToken(); break; } this.SkipTo(followers); return; case Token.Struct: this.GetNextToken(); tpar.TypeParameterFlags = TypeParameterFlags.ValueTypeConstraint; goto skipComma; } if (this.currentToken != Token.New) parameter.Interfaces = parameter.InterfaceExpressions = this.ParseInterfaceList(followers|Token.New, true); switch (this.currentToken){ case Token.Class: case Token.Struct: this.HandleError(Error.RefValBoundMustBeFirst); this.GetNextToken(); this.SkipTo(followers, Error.None); return; case Token.New: this.GetNextToken(); this.Skip(Token.LeftParenthesis); this.Skip(Token.RightParenthesis); tpar.TypeParameterFlags = TypeParameterFlags.DefaultConstructorConstraint; if (!followers[this.currentToken]) this.SkipTo(followers, Error.NewBoundMustBeLast); return; } }
public static TypeNode NewEqualTypeParameter(Duplicator dup, ITypeParameter itp, TypeNode declaringType, int index) { ClassParameter cp = itp as ClassParameter; if (cp != null) { ClassParameter mcp = new ClassParameter(); mcp.Interfaces = dup.VisitInterfaceReferenceList(cp.Interfaces); mcp.BaseClass = cp.BaseClass; mcp.TypeParameterFlags = cp.TypeParameterFlags & ~TypeParameterFlags.VarianceMask; mcp.DeclaringType = declaringType; mcp.DeclaringModule = declaringType.DeclaringModule; mcp.Name = cp.Name; mcp.ParameterListIndex = index; mcp.DeclaringMember = declaringType; return mcp; } TypeParameter tp = itp as TypeParameter; if (tp != null) { TypeParameter mp = new TypeParameter(); mp.Interfaces = dup.VisitInterfaceReferenceList(tp.Interfaces); mp.TypeParameterFlags = tp.TypeParameterFlags & ~TypeParameterFlags.VarianceMask; mp.DeclaringType = declaringType; mp.DeclaringModule = declaringType.DeclaringModule; mp.Name = tp.Name; mp.ParameterListIndex = index; mp.DeclaringMember = declaringType; return mp; } throw new NotImplementedException("unexpected type parameter kind"); }
public override TypeNode VisitTypeParameter(TypeNode typeParameter) { if(typeParameter == null) return null; TypeNode result = (TypeNode)this.DuplicateFor[typeParameter.UniqueKey]; if(result != null) return result; MethodTypeParameter mtp = typeParameter as MethodTypeParameter; if(mtp != null) { TypeParameter tp = new TypeParameter(); this.DuplicateFor[typeParameter.UniqueKey] = tp; tp.Name = mtp.Name; tp.Interfaces = this.VisitInterfaceReferenceList(mtp.Interfaces); tp.TypeParameterFlags = mtp.TypeParameterFlags; tp.DeclaringModule = mtp.DeclaringModule; tp.DeclaringMember = this.TargetType; result = tp; } else { MethodClassParameter mcp = typeParameter as MethodClassParameter; if(mcp != null) { ClassParameter cp = new ClassParameter(); this.DuplicateFor[typeParameter.UniqueKey] = cp; cp.Name = mcp.Name; cp.BaseClass = (Class)this.VisitTypeReference(mcp.BaseClass); cp.Interfaces = this.VisitInterfaceReferenceList(mcp.Interfaces); cp.TypeParameterFlags = mcp.TypeParameterFlags; cp.DeclaringModule = mcp.DeclaringModule; cp.DeclaringMember = this.TargetType; result = cp; } } if(result == null) return typeParameter; return result; }