//------------------------------------------------------------ // FUNCBREC.BindNubNew // /// <summary> /// Create an expr for new T?(exprSrc) where T is exprSrc->type. /// </summary> /// <param name="treeNode"></param> /// <param name="srcExpr"></param> /// <returns></returns> //------------------------------------------------------------ private EXPR BindNubNew(BASENODE treeNode, EXPR srcExpr) { DebugUtil.Assert(srcExpr != null); // Create a NUBSYM instance whose base bype is represented by srcExpr.TypeSym. NUBSYM nubSym = Compiler.MainSymbolManager.GetNubType(srcExpr.TypeSym); // Get a TYPESYM instance representing Nullable<> for nubSym. AGGTYPESYM aggTypeSym = nubSym.GetAggTypeSym(); if (aggTypeSym == null) { return(NewError(treeNode, nubSym)); } Compiler.EnsureState(aggTypeSym, AggStateEnum.Prepared); METHSYM methSym = Compiler.MainSymbolManager.NullableCtorMethodSym; if (methSym == null) { string name = Compiler.NameManager.GetPredefinedName(PREDEFNAME.CTOR); for (SYM sym = Compiler.MainSymbolManager.LookupAggMember(name, aggTypeSym.GetAggregate(), SYMBMASK.ALL); ; sym = sym.NextSameNameSym) { if (sym == null) { Compiler.Error(treeNode, CSCERRID.ERR_MissingPredefinedMember, new ErrArg(aggTypeSym), new ErrArg(name)); return(NewError(treeNode, nubSym)); } if (sym.IsMETHSYM) { methSym = sym as METHSYM; if (methSym.ParameterTypes.Count == 1 && methSym.ParameterTypes[0].IsTYVARSYM && methSym.Access == ACCESS.PUBLIC) { break; } } } Compiler.MainSymbolManager.NullableCtorMethodSym = methSym; } EXPRCALL resExpr = NewExpr(treeNode, EXPRKIND.CALL, nubSym) as EXPRCALL; resExpr.MethodWithInst.Set(methSym, aggTypeSym, BSYMMGR.EmptyTypeArray); resExpr.ArgumentsExpr = srcExpr; resExpr.ObjectExpr = null; resExpr.Flags |= EXPRFLAG.NEWOBJCALL | EXPRFLAG.CANTBENULL; return(resExpr); }
//------------------------------------------------------------ // FUNCBREC.BindNubGetValOrDef // /// <summary> /// Create an expr for exprSrc.GetValueOrDefault() /// where exprSrc->type is a NUBSYM. /// </summary> /// <param name="treeNode"></param> /// <param name="srcExpr"></param> /// <returns></returns> //------------------------------------------------------------ private EXPR BindNubGetValOrDef(BASENODE treeNode, EXPR srcExpr) { DebugUtil.Assert(srcExpr != null && srcExpr.TypeSym.IsNUBSYM); TYPESYM baseTypeSym = (srcExpr.TypeSym as NUBSYM).BaseTypeSym; // If srcExpr is null, just return the appropriate default value. if (srcExpr.GetConst() != null) { return(AddSideEffects(treeNode, NewExprZero(treeNode, baseTypeSym), srcExpr, true, true)); } // For new T?(x), the answer is x. if (IsNubCtor(srcExpr)) { DebugUtil.Assert( (srcExpr as EXPRCALL).ArgumentsExpr != null && (srcExpr as EXPRCALL).ArgumentsExpr.Kind != EXPRKIND.LIST); return((srcExpr as EXPRCALL).ArgumentsExpr); } AGGTYPESYM aggTypeSym = (srcExpr.TypeSym as NUBSYM).GetAggTypeSym(); if (aggTypeSym == null) { return(NewError(treeNode, baseTypeSym)); } Compiler.EnsureState(aggTypeSym, AggStateEnum.Prepared); METHSYM methSym = EnsureNubGetValOrDef(treeNode); if (methSym == null) { return(NewError(treeNode, baseTypeSym)); } CheckFieldUse(srcExpr, true); EXPRCALL resExpr = NewExpr(treeNode, EXPRKIND.CALL, baseTypeSym) as EXPRCALL; resExpr.MethodWithInst.Set(methSym, aggTypeSym, BSYMMGR.EmptyTypeArray); resExpr.ArgumentsExpr = null; resExpr.ObjectExpr = srcExpr; return(resExpr); }
//------------------------------------------------------------ // MemberLookup.LookupExtensionMethodInInterfaces // /// <summary></summary> /// <param name="startAggTypeSym"></param> /// <returns></returns> //------------------------------------------------------------ private bool LookupExtensionMethodInInterfaces(AGGTYPESYM startAggTypeSym) { //DebugUtil.Assert(this.firstSymWithType == null || this.isMulti); //DebugUtil.Assert(startAggTypeSym != null); if (startAggTypeSym == null) { return(false); } if (this.firstSymWithType != null && this.firstSymWithType.IsNotNull) { return(false); } //DebugUtil.Assert(startAggTypeSym == null || startAggTypeSym.IsInterfaceType()); //DebugUtil.Assert(startAggTypeSym != null || interfaceTypeArray.Count > 0); //DebugUtil.Assert((this.flags & // (MemLookFlagsEnum.Ctor | MemLookFlagsEnum.Operator | MemLookFlagsEnum.BaseCall)) // == 0); TypeArray interfaceTypeArray = startAggTypeSym.GetIfacesAll(); if (interfaceTypeArray == null || interfaceTypeArray.Count == 0) { return(false); } // Clear all the hidden flags. Anything found in a class hides any other // kind of member in all the interfaces. if (startAggTypeSym != null) { startAggTypeSym.AllHidden = false; startAggTypeSym.DiffHidden = (this.firstSymWithType != null); } for (int i = 0; i < interfaceTypeArray.Count; ++i) { AGGTYPESYM type = interfaceTypeArray[i] as AGGTYPESYM; DebugUtil.Assert(type.IsInterfaceType()); type.AllHidden = false; type.DiffHidden = (this.firstSymWithType != null); } if (startAggTypeSym != null) { Compiler.EnsureState(startAggTypeSym, AggStateEnum.Prepared); } if (interfaceTypeArray != null) { Compiler.EnsureState(interfaceTypeArray, AggStateEnum.Prepared); } //-------------------------------------------------------- // Loop through the interfaces. //-------------------------------------------------------- bool hideObject = false; int index = 0; AGGTYPESYM currentSym = interfaceTypeArray[index++] as AGGTYPESYM; DebugUtil.Assert(currentSym != null); for (; ;) { DebugUtil.Assert(currentSym != null && currentSym.IsInterfaceType()); bool hideByName = false; if (!currentSym.AllHidden && SearchSingleType(currentSym, out hideByName)) { SYM fsym = this.firstSymWithType.Sym; DebugUtil.Assert(fsym != null); if (fsym.Kind == SYMKIND.METHSYM && (fsym as METHSYM).IsInstanceExtensionMethod) { hideByName |= !this.isMulti; // Mark base interfaces appropriately. TypeArray interfaceArray = currentSym.GetIfacesAll(); for (int i = 0; i < interfaceArray.Count; ++i) { AGGTYPESYM sym = interfaceArray[i] as AGGTYPESYM; DebugUtil.Assert(sym.IsInterfaceType()); if (hideByName) { sym.AllHidden = true; } sym.DiffHidden = true; } // If we hide all base types, that includes object! if (hideByName) { hideObject = true; } } } this.flags &= ~MemLookFlagsEnum.TypeVarsAllowed; if (index >= interfaceTypeArray.Count) { return(!hideObject); } // Substitution has already been done. currentSym = interfaceTypeArray[index++] as AGGTYPESYM; } }
//------------------------------------------------------------ // FUNCBREC.BindNubHasValue // /// <summary> /// <para>Create an expr for exprSrc.HasValue where exprSrc->type is a NUBSYM.</para> /// <para>If fCheckTrue is false, invert the result.</para> /// <para>(In sscli, checkTrue has the default value true.)</para> /// </summary> /// <param name="treeNode"></param> /// <param name="srcExpr"></param> /// <param name="checkTrue"></param> /// <returns></returns> //------------------------------------------------------------ private EXPR BindNubHasValue( BASENODE treeNode, EXPR srcExpr, bool checkTrue) // = true { DebugUtil.Assert(srcExpr != null && srcExpr.TypeSym.IsNUBSYM); TYPESYM boolTypeSym = GetRequiredPredefinedType(PREDEFTYPE.BOOL); // When srcExpr is a null, the result is false if (srcExpr.GetConst() != null) { return(AddSideEffects( treeNode, NewExprConstant(treeNode, boolTypeSym, new ConstValInit(!checkTrue)), srcExpr, true, true)); } // For new T?(x), the answer is true. if (IsNubCtor(srcExpr)) { return(AddSideEffects( treeNode, NewExprConstant(treeNode, boolTypeSym, new ConstValInit(checkTrue)), StripNubCtor(srcExpr), true, true)); } AGGTYPESYM aggTypeSym = (srcExpr.TypeSym as NUBSYM).GetAggTypeSym(); if (aggTypeSym == null) { return(NewError(treeNode, boolTypeSym)); } Compiler.EnsureState(aggTypeSym, AggStateEnum.Prepared); PROPSYM propSym = EnsureNubHasValue(treeNode); if (propSym == null) { return(NewError(treeNode, boolTypeSym)); } CheckFieldUse(srcExpr, true); EXPRPROP resExpr = NewExpr(treeNode, EXPRKIND.PROP, boolTypeSym) as EXPRPROP; resExpr.SlotPropWithType.Set(propSym, aggTypeSym); resExpr.GetMethodWithType.Set(propSym.GetMethodSym, aggTypeSym); resExpr.ArgumentsExpr = null; resExpr.ObjectExpr = srcExpr; if (checkTrue) { return(resExpr); } return(NewExprBinop(treeNode, EXPRKIND.LOGNOT, resExpr.TypeSym, resExpr, null)); }