//------------------------------------------------------------ // CreateGetTypeFromHandleMethodSym // /// <summary> /// <para>Defined in FuncBindUtil.cs</para> /// </summary> /// <param name="treeNode"></param> /// <returns></returns> //------------------------------------------------------------ internal METHSYM CreateGetTypeFromHandleMethodSym(BASENODE treeNode) { if (GetTypeFromHandleMethodSym != null) { return(GetTypeFromHandleMethodSym); } // System.RuntimeTypeHandle TYPESYM handleTypeSym = this.GetRequiredPredefinedType(PREDEFTYPE.TYPEHANDLE); DebugUtil.Assert(handleTypeSym != null); TypeArray paramArray = new TypeArray(); paramArray.Add(handleTypeSym); paramArray = Compiler.MainSymbolManager.AllocParams(paramArray); GetTypeFromHandleMethodSym = FindPredefMeth( treeNode, PREDEFNAME.GETTYPEFROMHANDLE, this.GetRequiredPredefinedType(PREDEFTYPE.TYPE), paramArray, true, MemLookFlagsEnum.None); DebugUtil.Assert(GetTypeFromHandleMethodSym != null); return(GetTypeFromHandleMethodSym); }
//------------------------------------------------------------ // FUNCBREC.EnsureNubHasValue // /// <summary> /// Make sure the HasValue property of System.Nullable<T> is appropriate (and return it). /// </summary> /// <param name="treeNode"></param> /// <returns></returns> //------------------------------------------------------------ private PROPSYM EnsureNubHasValue(BASENODE treeNode) { PROPSYM propSym = Compiler.MainSymbolManager.NullableHasValuePropertySym; if (propSym == null) { AGGSYM nubAggSym = Compiler.GetOptPredefAggErr(PREDEFTYPE.G_OPTIONAL, true); if (nubAggSym == null) { return(null); } string name = Compiler.NameManager.GetPredefinedName(PREDEFNAME.HASVALUE); SYM sym = Compiler.MainSymbolManager.LookupAggMember( name, nubAggSym, SYMBMASK.PROPSYM); propSym = sym as PROPSYM; if (propSym == null || propSym.IsStatic || propSym.Access != ACCESS.PUBLIC || propSym.ParameterTypes.Count > 0 || !propSym.ReturnTypeSym.IsPredefType(PREDEFTYPE.BOOL) || propSym.GetMethodSym == null) { Compiler.Error(treeNode, CSCERRID.ERR_MissingPredefinedMember, new ErrArg(nubAggSym), new ErrArg(name)); return(null); } Compiler.MainSymbolManager.NullableHasValuePropertySym = propSym; } return(propSym); }
//------------------------------------------------------------ // CLSDREC.SetForPartialMethod // /// <summary></summary> /// <param name="treeNode"></param> /// <param name="partialMethSym">the partial method</param> /// <param name="otherMethSym">the other method with the same signiture</param> /// <param name="errorID"></param> /// <returns></returns> //------------------------------------------------------------ internal bool CheckForDulicatePartialMethod( BASENODE treeNode, METHSYM partialMethSym, METHSYM otherMethSym) { if (partialMethSym == null || otherMethSym == null) { return(true); } if (!otherMethSym.IsPartialMethod) { Compiler.Error( treeNode, CSCERRID.ERR_MemberAlreadyExists, new ErrArg(partialMethSym), new ErrArg(partialMethSym.ClassSym)); return(false); } if (!partialMethSym.HasNoBody && !otherMethSym.HasNoBody) { Compiler.Error( treeNode, CSCERRID.ERR_MultiplePartialMethodImplementation); return(false); } return(true); }
//------------------------------------------------------------ // FUNCBREC.BindNubValue // /// <summary> /// Create an expr for exprSrc.Value where exprSrc->type is a NUBSYM. /// </summary> /// <param name="treeNode"></param> /// <param name="srcExpr"></param> /// <returns></returns> //------------------------------------------------------------ private EXPR BindNubValue(BASENODE treeNode, EXPR srcExpr) { DebugUtil.Assert(srcExpr != null && srcExpr.TypeSym.IsNUBSYM); // 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); } TYPESYM baseTypeSym = (srcExpr.TypeSym as NUBSYM).BaseTypeSym; AGGTYPESYM ats = (srcExpr.TypeSym as NUBSYM).GetAggTypeSym(); if (ats == null) { return(NewError(treeNode, baseTypeSym)); } compiler.EnsureState(ats, AggStateEnum.Prepared); PROPSYM propertySym = compiler.MainSymbolManager.NullableValuePropertySym; if (propertySym == null) { string name = compiler.NameManager.GetPredefinedName(PREDEFNAME.CAP_VALUE); propertySym = compiler.MainSymbolManager.LookupAggMember( name, ats.GetAggregate(), SYMBMASK.PROPSYM) as PROPSYM; if (propertySym == null || propertySym.IsStatic || propertySym.Access != ACCESS.PUBLIC || propertySym.ParameterTypes.Count > 0 || !propertySym.ReturnTypeSym.IsTYVARSYM || propertySym.GetMethodSym == null) { compiler.Error( treeNode, CSCERRID.ERR_MissingPredefinedMember, new ErrArg(ats), new ErrArg(name)); return(NewError(treeNode, baseTypeSym)); } compiler.MainSymbolManager.NullableValuePropertySym = propertySym; } CheckFieldUse(srcExpr, true); EXPRPROP propertyExpr = NewExpr(treeNode, EXPRKIND.PROP, baseTypeSym) as EXPRPROP; propertyExpr.SlotPropWithType.Set(propertySym, ats); propertyExpr.GetMethodWithType.Set(propertySym.GetMethodSym, ats); propertyExpr.ArgumentsExpr = null; propertyExpr.ObjectExpr = srcExpr; return(propertyExpr); }
//------------------------------------------------------------ // ERRLOC Constructor (3) // /// <para>Constructor.</para> /// <para>Get the current position from the BASENODE argument and /// mapping information from INFILESYM.SourceData of BSYMMGR.</para> /// <param name="symmgr"></param> /// <param name="node"></param> //------------------------------------------------------------ internal ERRLOC(BSYMMGR symmgr, BASENODE node, bool fullPath) { if (node != null) { DebugUtil.Assert(symmgr != null); string inputFileName = node.GetContainingFileName(fullPath); INFILESYM inputFile = symmgr.FindInfileSym(inputFileName); sourceFileName = inputFileName; sourceMapFileName = inputFileName; if (inputFile != null) { sourceData = inputFile.SourceData; SetLine(node); SetStart(node); SetEnd(node); mapStartPos = (startPos != null ? startPos.Clone() : null); mapEndPos = (endPos != null ? endPos.Clone() : null); string sd; bool bd1, bd2; sourceData.Module.MapLocation(mapStartPos, out sourceMapFileName, out bd1, out bd2); sourceData.Module.MapLocation(mapEndPos, out sd, out bd1, out bd2); return; } } }
//------------------------------------------------------------ // FUNCBREC.AddSideEffects // /// <summary> /// <para>Add sideExpr to baseExpr as a side effect.</para> /// <para>If isPre is true, sideExpr is evaluated before baseExpr.</para> /// <para>If sideExpr is NULL or contains no side effects, just returns baseExpr.</para> /// <para>If no side effect, return baseExpr. /// Otherwise create and return an EXPRBINOP instance of /// whose operands are sideExpr and baseExpr.</para> /// </summary> /// <param name="treeNode"></param> /// <param name="baseExpr"></param> /// <param name="sideExpr"></param> /// <param name="isPre"></param> /// <param name="forceNonConst"></param> /// <returns></returns> //------------------------------------------------------------ private EXPR AddSideEffects( BASENODE treeNode, EXPR baseExpr, EXPR sideExpr, bool isPre, bool forceNonConst) // = false { if (sideExpr == null) { return(baseExpr); } if (!sideExpr.HasSideEffects(Compiler)) { // Make sure it's not an lvalue or constant (unless sideExpr is a constant and !forceNonConst). if (((baseExpr.Flags & EXPRFLAG.LVALUE) == 0) && (baseExpr.Kind != EXPRKIND.CONSTANT || sideExpr.Kind == EXPRKIND.CONSTANT && !forceNonConst)) { return(baseExpr); } return(NewExprBinop( treeNode, EXPRKIND.SEQUENCE, baseExpr.TypeSym, NewExpr(treeNode, EXPRKIND.NOOP, GetVoidType()), baseExpr)); } if (isPre) { return(NewExprBinop(treeNode, EXPRKIND.SEQUENCE, baseExpr.TypeSym, sideExpr, baseExpr)); } return(NewExprBinop(treeNode, EXPRKIND.SEQREV, baseExpr.TypeSym, baseExpr, sideExpr)); }
//------------------------------------------------------------ // ERRLOC Constructor (2) // /// <summary> /// <para>Constructor.</para> /// <para>Get the current position from the BASENODE argument and /// mapping information from INFILESYM.SourceData.</para> /// </summary> /// <param name="inputFile"></param> /// <param name="node"></param> //------------------------------------------------------------ internal ERRLOC(INFILESYM inputFile, BASENODE node, bool fullPath) { DebugUtil.Assert(inputFile != null); sourceData = inputFile.SourceData; sourceFileName = (fullPath ? inputFile.FullName : inputFile.Name); sourceMapFileName = inputFile.Name; if (node != null) { SetLine(node); SetStart(node); this.endPos = new POSDATA(); //endPos.SetUninitialized(); SetEnd(node); mapStartPos = (startPos != null ? startPos.Clone() : null); mapEndPos = (endPos != null ? endPos.Clone() : null); string sd; // dummy bool bd1, bd2; // dummy // mapStart、mapEnd の行番号をマップ先のもので置き換え、ファイル名を取得する。 sourceData.Module.MapLocation(mapStartPos, out sourceMapFileName, out bd1, out bd2); sourceData.Module.MapLocation(mapEndPos, out sd, out bd1, out bd2); } }
//------------------------------------------------------------ // CSourceData.LookupNode //------------------------------------------------------------ //STDMETHODIMP CSourceData::LookupNode ( // NAME *pKey, long iOrdinal, BASENODE **ppNode, long *piGlobalOrdinal) //virtual internal int LookupNode( // ref string pKey, int iOrdinal, ref BASENODE ppNode, ref int piGlobalOrdinal) //{ // return sourceModuleBase.LookupNode (this, pKey, iOrdinal, ppNode, piGlobalOrdinal); //} //------------------------------------------------------------ // CSourceData.GetNodeKeyOrdinal //------------------------------------------------------------ //STDMETHODIMP CSourceData::GetNodeKeyOrdinal (BASENODE *pNode, NAME **ppKey, long *piKeyOrdinal) //virtual internal int GetNodeKeyOrdinal(BASENODE pNode, ref string ppKey, ref int piKeyOrdinal) //{ // return sourceModuleBase.GetNodeKeyOrdinal (this, pNode, ppKey, piKeyOrdinal); //} //------------------------------------------------------------ // CSourceData.GetGlobalKeyArray //------------------------------------------------------------ //STDMETHODIMP CSourceData::GetGlobalKeyArray (KEYEDNODE *pKeyedNodes, long iSize, long *piCopied) //virtual internal int GetGlobalKeyArray(KEYEDNODE pKeyedNodes, int iSize, ref int piCopied) //{ // return sourceModuleBase.GetGlobalKeyArray (this, pKeyedNodes, iSize, piCopied); //} //------------------------------------------------------------ // CSourceData.ParseForErrors //------------------------------------------------------------ //STDMETHODIMP CSourceData::ParseForErrors () //virtual internal int ParseForErrors() //{ // return sourceModuleBase.ParseForErrors (this); //} //------------------------------------------------------------ // CSourceData.FindLeafNode //------------------------------------------------------------ //STDMETHODIMP CSourceData::FindLeafNode ( // const POSDATA pos, BASENODE **ppNode, ICSInteriorTree **ppTree) //virtual internal int FindLeafNode(POSDATA pos, ref BASENODE ppNode, ref CInteriorTree ppTree) //{ // return FindLeafNodeEx(pos, EF_FULL, ppNode, ppTree); //} //------------------------------------------------------------ // CSourceData.FindLeafNodeForToken //------------------------------------------------------------ //STDMETHODIMP CSourceData::FindLeafNodeForToken ( // long iToken, BASENODE **ppNode, ICSInteriorTree **ppTree) //virtual internal int FindLeafNodeForToken( // int iToken, ref BASENODE ppNode, ref CInteriorTree ppTree) //{ // return FindLeafNodeForTokenEx(iToken, EF_FULL, ppNode, ppTree); //} //------------------------------------------------------------ // CSourceData.FindLeafNodeEx //------------------------------------------------------------ //STDMETHODIMP CSourceData::FindLeafNodeEx ( // const POSDATA pos, ExtentFlags flags, BASENODE **ppNode, ICSInteriorTree **ppTree) //virtual internal int FindLeafNodeEx( // POSDATA pos, ExtentFlags flags, ref BASENODE ppNode, ref CInteriorTree ppTree) //{ // return sourceModuleBase.FindLeafNodeEx (this, pos, flags, ppNode, ppTree); //} //------------------------------------------------------------ // CSourceData.FindLeafNodeForTokenEx //------------------------------------------------------------ //STDMETHODIMP CSourceData::FindLeafNodeForTokenEx ( // long iToken, ExtentFlags flags, BASENODE **ppNode, ICSInteriorTree **ppTree) //virtual internal int FindLeafNodeForTokenEx( // int iToken, ExtentFlags flags, ref BASENODE ppNode, ref CInteriorTree ppTree) //{ // return sourceModuleBase.FindLeafNodeForTokenEx (this, iToken, flags, ppNode, ppTree); //} //------------------------------------------------------------ // CSourceData.GetExtent //------------------------------------------------------------ //virtual internal int GetExtent(BASENODE pNode, POSDATA pposStart, POSDATA pposEnd) //{ //} //STDMETHODIMP CSourceData::GetExtent(BASENODE *pNode, POSDATA *pposStart, POSDATA *pposEnd) { // return GetExtentEx( pNode, pposStart, pposEnd, EF_FULL); //}; //------------------------------------------------------------ // CSourceData.GetExtentEx // /// <summary></summary> /// <param name="node"></param> /// <param name="start"></param> /// <param name="end"></param> /// <param name="flags"></param> /// <returns></returns> //------------------------------------------------------------ virtual internal bool GetExtentEx( BASENODE node, POSDATA start, POSDATA end, ExtentFlags flags) { return(sourceModuleBase.GetExtent(node, start, end, flags)); }
//------------------------------------------------------------ // FUNCBREC.BindImplicitlyTypedArrayInitCore // /// <summary></summary> /// <param name="treeUnOpNode"></param> /// <param name="elementTypeSym"></param> /// <param name="dimList"></param> /// <param name="dimIndex"></param> /// <param name="topArgList"></param> //------------------------------------------------------------ internal void BindImplicitlyTypedArrayInitCore( UNOPNODE treeUnOpNode, ref TYPESYM elementTypeSym, List <int> dimList, int dimIndex, ref EXPR topArgList) { int count = 0; EXPR lastArgList = null; BASENODE node = treeUnOpNode.Operand; while (node != null) { BASENODE itemNode; if (node.Kind == NODEKIND.LIST) { itemNode = node.AsLIST.Operand1.AsBASE; node = node.AsLIST.Operand2; } else { itemNode = node.AsBASE; node = null; } count++; EXPR expr = BindExpr(itemNode, BindFlagsEnum.RValueRequired); if (elementTypeSym == null || elementTypeSym.Kind == SYMKIND.IMPLICITTYPESYM) { elementTypeSym = expr.TypeSym; } else if (CanConvert(elementTypeSym, expr.TypeSym, ConvertTypeEnum.STANDARD)) { elementTypeSym = expr.TypeSym; } else if (!CanConvert(expr.TypeSym, elementTypeSym, ConvertTypeEnum.STANDARD)) { // do nothing here. } NewList(expr, ref topArgList, ref lastArgList); //exprList.Add(expr); } if (dimList[dimIndex] != -1) { if (dimList[dimIndex] != count) { Compiler.Error(treeUnOpNode, CSCERRID.ERR_InvalidArray); } } else { dimList[dimIndex] = count; } }
//------------------------------------------------------------ // CInteriorTree.Initialize // /// <summary> /// Set this.interiorNode and return true. /// </summary> /// <param name="data"></param> /// <param name="node"></param> /// <returns></returns> //------------------------------------------------------------ internal bool Initialize(CSourceData data, BASENODE node) { sourceData = data; #if DEBUG debugThread = Thread.CurrentThread; #endif interiorNode = data.Module.GetInteriorNode(data, node); return(true); }
//------------------------------------------------------------ // CLSDREC.IsAutoImplementedAccessor // /// <summary></summary> /// <param name="methodSym"></param> /// <returns></returns> //------------------------------------------------------------ internal static bool IsAutoImplementedAccessor(BASENODE node) { if (node == null || node.Kind != NODEKIND.ACCESSOR) { return(false); } return((node as ACCESSORNODE).IsAutoImplemented); }
//------------------------------------------------------------ // CLSDREC.SetForPartialMethod // /// <summary></summary> /// <param name="treeNode"></param> /// <param name="methodSym"></param> //------------------------------------------------------------ internal void SetForPartialMethod(BASENODE treeNode, METHSYM methodSym) { if (!IsPartialMethod(treeNode)) { return; } methodSym.IsPartialMethod = true; methodSym.HasNoBody = ((treeNode.NodeFlagsEx & NODEFLAGS.EX_METHOD_NOBODY) != 0); }
//private ~CInteriorTree(); //------------------------------------------------------------ // CInteriorTree.CreateInstance // /// <summary> /// Create a CInteriorTree instance and initialize it with the arguments. /// </summary> /// <param name="data"></param> /// <param name="node"></param> /// <returns></returns> //------------------------------------------------------------ static internal CInteriorTree CreateInstance(CSourceData data, BASENODE node) { CInteriorTree tree = new CInteriorTree(); if (tree.Initialize(data, node)) { return(tree); } return(null); }
//------------------------------------------------------------ // 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); }
//------------------------------------------------------------ // CLSDREC.IsPartialMethod // /// <summary></summary> /// <param name="node"></param> /// <returns></returns> //------------------------------------------------------------ internal bool IsPartialMethod(BASENODE treeNode) { DebugUtil.Assert(treeNode != null); if (treeNode.Kind != NODEKIND.METHOD) { return(false); } return((treeNode.Flags & NODEFLAGS.MOD_PARTIAL) != 0); }
//------------------------------------------------------------ // FUNCBREC.BindNubFetchAndFree // /// <summary> /// If the given slot has a temp associated with it, /// constructs a reverse sequence for loading the value and freeing the temp. /// Otherwise, just returns the value expr. /// </summary> /// <param name="treeNode"></param> /// <param name="nubInfo"></param> /// <param name="iexpr"></param> /// <returns></returns> //------------------------------------------------------------ private EXPR BindNubFetchAndFree(BASENODE treeNode, ref NubInfo nubInfo, int iexpr) { EXPR expr = nubInfo.TmpExpr[iexpr]; DebugUtil.Assert(expr != null); if (nubInfo.PostExpr[iexpr] == null) { return(expr); } return(AddSideEffects(treeNode, expr, nubInfo.PostExpr[iexpr], false, true)); }
//------------------------------------------------------------ // FUNCBREC.EnsureNonConstNonLvalue // /// <summary> /// If exprBase is a constant or lvalue, /// sequence it with EK_NOOP so it doesn't appear to be either. /// </summary> /// <param name="tree"></param> /// <param name="exprBase"></param> /// <returns></returns> //------------------------------------------------------------ private EXPR EnsureNonConstNonLvalue(BASENODE tree, EXPR exprBase) { if ((exprBase.Flags & EXPRFLAG.LVALUE) == 0 && exprBase.Kind != EXPRKIND.CONSTANT) { return(exprBase); } return(NewExprBinop( tree, EXPRKIND.SEQUENCE, exprBase.TypeSym, NewExpr(tree, EXPRKIND.NOOP, GetVoidType()), exprBase)); }
static internal void DebugNodesAdd(BASENODE node) { if (node == null) { return; } try { NodeDictionary.Add(node.NodeID, node); } catch (ArgumentException) { } }
//------------------------------------------------------------ // 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); }
//------------------------------------------------------------ // FUNCBREC.BindNubOpRes (1) // /// <summary> /// <para>Combine the condition and value.</para> /// <para>(In sscli, warOnNull has the default value false.)</para> /// </summary> /// <param name="treeNode"></param> /// <param name="nubSym"></param> /// <param name="dstTypeSym"></param> /// <param name="valueExpr"></param> /// <param name="nubInfo"></param> /// <param name="warnOnNull"></param> /// <returns></returns> //------------------------------------------------------------ private EXPR BindNubOpRes( BASENODE treeNode, NUBSYM nubSym, TYPESYM dstTypeSym, EXPR valueExpr, ref NubInfo nubInfo, bool warnOnNull) // = false { if (nubInfo.FAlwaysNull() && warnOnNull) { Compiler.Error(treeNode, CSCERRID.WRN_AlwaysNull, new ErrArg(nubSym)); } return(BindNubOpRes( treeNode, dstTypeSym, valueExpr, NewExprZero(treeNode, dstTypeSym.IsNUBSYM ? dstTypeSym : nubSym), ref nubInfo)); }
//------------------------------------------------------------ // FUNCBREC.EnsureNubGetValOrDef // /// <summary> /// Make sure the HasValue property of System.Nullable<T> is appropriate (and return it). /// </summary> /// <param name="treeNode"></param> /// <returns></returns> //------------------------------------------------------------ private METHSYM EnsureNubGetValOrDef(BASENODE treeNode) { METHSYM methSym = Compiler.MainSymbolManager.NullableGetValOrDefMethodSym; if (methSym == null) { AGGSYM nubAggSym = Compiler.GetOptPredefAggErr(PREDEFTYPE.G_OPTIONAL, true); if (nubAggSym == null) { return(null); } string name = Compiler.NameManager.GetPredefinedName(PREDEFNAME.GET_VALUE_OR_DEF); for (SYM sym = Compiler.MainSymbolManager.LookupAggMember(name, nubAggSym, SYMBMASK.ALL); ; sym = sym.NextSameNameSym) { if (sym == null) { Compiler.Error(treeNode, CSCERRID.ERR_MissingPredefinedMember, new ErrArg(nubAggSym), new ErrArg(name)); return(null); } if (sym.IsMETHSYM) { methSym = sym as METHSYM; if (methSym.ParameterTypes.Count == 0 && methSym.ParameterTypes.Count == 0 && methSym.ReturnTypeSym.IsTYVARSYM && !methSym.IsStatic && methSym.Access == ACCESS.PUBLIC) { break; } } } Compiler.MainSymbolManager.NullableGetValOrDefMethodSym = methSym; } return(methSym); }
//------------------------------------------------------------ // CLSDREC.CheckFlagsAndSigOfPartialMethod // /// <summary></summary> /// <param name="nodeFlags"></param> /// <param name="methodSym"></param> /// <returns></returns> //------------------------------------------------------------ internal void CheckFlagsAndSigOfPartialMethod( BASENODE treeNode, NODEFLAGS nodeFlags, METHSYM methodSym) { const NODEFLAGS forbidden = 0 | NODEFLAGS.MOD_ABSTRACT | NODEFLAGS.MOD_NEW | NODEFLAGS.MOD_OVERRIDE | NODEFLAGS.MOD_PRIVATE | NODEFLAGS.MOD_PROTECTED | NODEFLAGS.MOD_INTERNAL | NODEFLAGS.MOD_PUBLIC | NODEFLAGS.MOD_SEALED | NODEFLAGS.MOD_VIRTUAL | NODEFLAGS.MOD_EXTERN; if ((nodeFlags & forbidden) != 0) { Compiler.Error(treeNode, CSCERRID.ERR_BadModifierForPartialMethod); } TypeArray paramTypes = methodSym.ParameterTypes; if (paramTypes != null && paramTypes.Count > 0) { for (int i = 0; i < paramTypes.Count; ++i) { TYPESYM typeSym = paramTypes[i]; if (typeSym.Kind == SYMKIND.PARAMMODSYM && (typeSym as PARAMMODSYM).IsOut) { Compiler.Error( treeNode, CSCERRID.ERR_PartialMethodHasOutParameter); } } } }
//------------------------------------------------------------ // FUNCBREC.BindNubAddTmps // /// <summary> /// Combines the pre and post expressions of the NubInfo with exprRes. /// The pre and post exprs are typically to store values to temps and free the temps. /// </summary> /// <param name="treeNode"></param> /// <param name="resExpr"></param> /// <param name="nubInfo"></param> /// <returns></returns> //------------------------------------------------------------ private EXPR BindNubAddTmps(BASENODE treeNode, EXPR resExpr, ref NubInfo nubInfo) { if (nubInfo.PostExpr[1] != null) { resExpr = NewExprBinop(treeNode, EXPRKIND.SEQREV, resExpr.TypeSym, resExpr, nubInfo.PostExpr[1]); } if (nubInfo.PostExpr[0] != null) { resExpr = NewExprBinop(treeNode, EXPRKIND.SEQREV, resExpr.TypeSym, resExpr, nubInfo.PostExpr[0]); } if (nubInfo.PreExpr[1] != null) { resExpr = NewExprBinop(treeNode, EXPRKIND.SEQUENCE, resExpr.TypeSym, nubInfo.PreExpr[1], resExpr); } if (nubInfo.PreExpr[0] != null) { resExpr = NewExprBinop(treeNode, EXPRKIND.SEQUENCE, resExpr.TypeSym, nubInfo.PreExpr[0], resExpr); } return(resExpr); }
//------------------------------------------------------------ // FUNCBREC.BindUnaryOperator // // EXPR * BindStdUnaOp(BASENODE * tree, OPERATOR op, EXPR * arg); // EXPR * BindIntUnaOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg); // EXPR * BindRealUnaOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg); // EXPR * BindDecUnaOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg); // EXPR * BindBoolUnaOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg); // EXPR * BindEnumUnaOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg); //------------------------------------------------------------ internal EXPR BindUnaryOperator( BindUnaOpEnum op, BASENODE tree, EXPRKIND ek, EXPRFLAG flags, EXPR arg) { switch (op) { case BindUnaOpEnum.Integer: // Handles standard unary integer based operators. // EXPR * FUNCBREC::BindIntUnaOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg) DebugUtil.Assert(arg.TypeSym.IsPredefined()); return(BindIntOp(tree, ek, flags, arg, null, arg.TypeSym.GetPredefType())); case BindUnaOpEnum.Real: // Handles standard unary floating point (float, double) based operators. // EXPR * FUNCBREC::BindRealUnaOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg) DebugUtil.Assert(arg.TypeSym.IsPredefined()); return(BindFloatOp(tree, ek, flags, arg, null)); case BindUnaOpEnum.Decimal: return(BindDecUnaOp(tree, ek, flags, arg)); case BindUnaOpEnum.Bool: return(BindBoolUnaOp(tree, ek, flags, arg)); break; case BindUnaOpEnum.Enum: return(BindEnumUnaOp(tree, ek, flags, arg)); default: DebugUtil.Assert(false, "FUNCBREC.BindUnaryOperator"); break; } return(null); }
//------------------------------------------------------------ // FUNCBREC.BindQMark // /// <summary> /// <para>Constructs an expr for "exprCond ? exprLeft : exprRight". If fInvert is true, reverses /// exprLeft and exprRight.</para> /// <para>(In sscli, fInvert has the default value false.)</para> /// </summary> /// <remarks> /// REVIEW ShonK: Optimize BindQmark when the condition is a constant (with possible side effects). /// </remarks> /// <param name="tree"></param> /// <param name="condExpr"></param> /// <param name="leftExpr"></param> /// <param name="rightExpr"></param> /// <param name="fInvert"></param> /// <returns></returns> //------------------------------------------------------------ private EXPR BindQMark( BASENODE tree, EXPR condExpr, EXPR leftExpr, EXPR rightExpr, bool fInvert) // =false { DebugUtil.Assert(condExpr.TypeSym.IsPredefType(PREDEFTYPE.BOOL)); DebugUtil.Assert(leftExpr.TypeSym == rightExpr.TypeSym); EXPR colonExpr; if (fInvert) { colonExpr = NewExprBinop(tree, EXPRKIND.BINOP, null, rightExpr, leftExpr); } else { colonExpr = NewExprBinop(tree, EXPRKIND.BINOP, null, leftExpr, rightExpr); } return(NewExprBinop(tree, EXPRKIND.QMARK, leftExpr.TypeSym, condExpr, colonExpr)); }
//------------------------------------------------------------ // FUNCBREC.BindNubOpRes (2) // /// <summary> /// Combine the condition and value. /// </summary> /// <param name="treeNode"></param> /// <param name="dstTypeSym"></param> /// <param name="valueExpr"></param> /// <param name="nullExpr"></param> /// <param name="nubInfo"></param> /// <returns></returns> //------------------------------------------------------------ private EXPR BindNubOpRes( BASENODE treeNode, TYPESYM dstTypeSym, EXPR valueExpr, EXPR nullExpr, ref NubInfo nubInfo) { EXPR resExpr; nullExpr = MustConvert(nullExpr, dstTypeSym, 0); valueExpr = MustConvert(valueExpr, dstTypeSym, 0); if (nubInfo.FAlwaysNonNull()) { // Don't need nullExpr and there aren't any temps. resExpr = valueExpr; } else if (nubInfo.FAlwaysNull()) { // Don't need valueExpr but do need side effects. resExpr = BindNubAddTmps(treeNode, nullExpr, ref nubInfo); } else { DebugUtil.Assert(nubInfo.CombinedConditionExpr != null); resExpr = BindQMark( treeNode, nubInfo.CombinedConditionExpr, MustConvert(valueExpr, dstTypeSym, 0), nullExpr, false); resExpr = BindNubAddTmps(treeNode, resExpr, ref nubInfo); } return(resExpr); }
//------------------------------------------------------------ // MetaDataHelper.GetExplicitImplName // /// <summary> /// Get a synthesized name for explicit interface implementations. /// The name we use is: "InterfaceName.MethodName", where InterfaceName is the fully qualified name /// of the interface containing the implemented method. /// This name has a '.' in it, so it can't conflict with any "real" name or be confused with one. /// </summary> /// <remarks> /// Returns true if the buffer had enough space for the name. /// If not enough space, then adds as much of name as possible to buffer. /// Always NULL terminates buffer. /// </remarks> /// <param name="sym"></param> /// <param name="strBuilder"></param> //------------------------------------------------------------ public void GetExplicitImplName(SYM sym, StringBuilder strBuilder) { DebugUtil.Assert(sym.IsEVENTSYM || sym.IsMETHPROPSYM); SymWithType swtImpl = new SymWithType(); ERRORSYM errSym = null; string implName = null; string aliasName = null; switch (sym.Kind) { case SYMKIND.EVENTSYM: EVENTSYM eventSym = sym as EVENTSYM; DebugUtil.Assert(eventSym.IsExpImpl); swtImpl = eventSym.SlotEventWithType; errSym = eventSym.ExpImplErrorSym; break; case SYMKIND.METHSYM: case SYMKIND.PROPSYM: { METHPROPSYM mpSym = sym as METHPROPSYM; DebugUtil.Assert(mpSym.IsExplicitImplementation); swtImpl = mpSym.SlotSymWithType; errSym = mpSym.ExpImplErrorSym; BASENODE nameNode = null; if (sym.IsMETHSYM && (sym as METHSYM).ParseTreeNode != null && (sym as METHSYM).ParseTreeNode.Kind == NODEKIND.METHOD) { nameNode = ((sym as METHSYM).ParseTreeNode as METHODNODE).NameNode; } else if ( sym.IsPROPSYM && (sym as PROPSYM).ParseTreeNode != null && (sym as PROPSYM).ParseTreeNode.Kind == NODEKIND.PROPERTY) { nameNode = ((sym as PROPSYM).ParseTreeNode as PROPERTYNODE).NameNode; } while (nameNode != null && nameNode.Kind == NODEKIND.DOT) { nameNode = nameNode.AsDOT.Operand1; } if (nameNode != null && nameNode.Kind == NODEKIND.ALIASNAME) { aliasName = nameNode.AsANYNAME.Name; } if (!sym.IsPROPSYM || !(sym as PROPSYM).IsIndexer) { break; } implName = (swtImpl != null ? (swtImpl.Sym as PROPSYM).GetRealName() : "Item"); // fish out any user specified alias break; } default: // gcc -Wall (all warnings enabled) complains if all cases // aren't handled, so we explicitly handle default and assert DebugUtil.Assert(false); break; } DebugUtil.Assert(swtImpl != null || errSym != null); if (aliasName != null) { strBuilder.Append(aliasName); strBuilder.Append("::"); } if (swtImpl != null) { GetExplicitImplTypeName(swtImpl.AggTypeSym, strBuilder); if (implName == null) { implName = swtImpl.Sym.Name; } } else { GetExplicitImplTypeName(errSym, strBuilder); } if (implName != null) { // Add dot seperator. strBuilder.Append('.'); strBuilder.Append(implName); } }
//------------------------------------------------------------ // FUNCBREC.BindNubConstBool // /// <summary> /// Return an expr for "new bool?(fT)". /// </summary> /// <param name="tree"></param> /// <param name="fT"></param> /// <returns></returns> //------------------------------------------------------------ private EXPR BindNubConstBool(BASENODE tree, bool fT) { EXPR expr = NewExprConstant(tree, GetRequiredPredefinedType(PREDEFTYPE.BOOL), new ConstValInit(fT)); return(BindNubNew(tree, expr)); }
//------------------------------------------------------------ // FUNCBREC.BindNubCondValBin // /// <summary> /// <para>Fill in the NubInfo for a unary or binary operator lifting.</para> /// <para>(In sscli, liftFlags has default value LiftFlags::LiftBoth.)</para> /// </summary> /// <param name="treeNode"></param> /// <param name="expr1"></param> /// <param name="expr2"></param> /// <param name="nubInfo"></param> /// <param name="liftFlags"></param> //------------------------------------------------------------ private void BindNubCondValBin( BASENODE treeNode, EXPR expr1, EXPR expr2, ref NubInfo nubInfo, LiftFlagsEnum liftFlags) // = LiftFlags::LiftBoth { DebugUtil.Assert((liftFlags & (LiftFlagsEnum.Lift1 | LiftFlagsEnum.Lift2)) != 0); DebugUtil.Assert(expr1 != null); DebugUtil.Assert(expr2 != null || (liftFlags & LiftFlagsEnum.Lift1) != 0); nubInfo.Init(); bool[] rgfLift = { false, false }; rgfLift[0] = ((liftFlags & LiftFlagsEnum.Lift1) != 0); rgfLift[1] = expr2 != null && ((liftFlags & LiftFlagsEnum.Lift2) != 0); EXPR[] rgexpr = { null, null }; rgexpr[0] = rgfLift[0] ? StripNubCtor(expr1) : expr1; rgexpr[1] = rgfLift[1] ? StripNubCtor(expr2) : expr2; if ((!rgfLift[0] || !rgexpr[0].TypeSym.IsNUBSYM) && (!rgfLift[1] || !rgexpr[1].TypeSym.IsNUBSYM)) { // All lifted params can't be null so we don't need temps. nubInfo.ValueExpr[0] = rgexpr[0]; nubInfo.ValueExpr[1] = rgexpr[1]; nubInfo.IsActive = true; nubInfo.IsAlwaysNonNull = true; return; } // Optimization: if they are the same local then we only need one temp. if (rgexpr[1] != null && rgexpr[0].Kind == EXPRKIND.LOCAL && rgexpr[1].Kind == EXPRKIND.LOCAL && (rgexpr[0] as EXPRLOCAL).LocVarSym == (rgexpr[1] as EXPRLOCAL).LocVarSym && rgfLift[0] == rgfLift[1]) { BindNubSave(rgexpr[0], ref nubInfo, 0, rgfLift[0]); DebugUtil.Assert(nubInfo.TmpExpr[0].Kind == EXPRKIND.LDTMP); nubInfo.TmpExpr[1] = nubInfo.TmpExpr[0]; nubInfo.IsSameTemp = true; } else { BindNubSave(rgexpr[0], ref nubInfo, 0, rgfLift[0]); if (rgexpr[1] != null) { BindNubSave(rgexpr[1], ref nubInfo, 1, rgfLift[1]); } } for (int iexpr = 0; iexpr < 2 && rgexpr[iexpr] != null; iexpr++) { if (!rgfLift[iexpr] || !nubInfo.TmpExpr[iexpr].TypeSym.IsNUBSYM) { nubInfo.ValueExpr[iexpr] = nubInfo.TmpExpr[iexpr]; continue; } nubInfo.ValueExpr[iexpr] = BindNubGetValOrDef(treeNode, nubInfo.TmpExpr[iexpr]); DebugUtil.Assert(!nubInfo.ValueExpr[iexpr].TypeSym.IsNUBSYM); if (nubInfo.FConst(iexpr)) { nubInfo.IsNull[iexpr] = nubInfo.IsAlwaysNull = true; } else if (nubInfo.IsSameTemp && iexpr != 0) { nubInfo.ConditionExpr[iexpr] = nubInfo.ConditionExpr[0]; } else { nubInfo.ConditionExpr[iexpr] = BindNubHasValue(treeNode, nubInfo.TmpExpr[iexpr], true); } } if (!nubInfo.IsAlwaysNull) { if (nubInfo.ConditionExpr[0] == null) { nubInfo.CombinedConditionExpr = nubInfo.ConditionExpr[1]; } else if (nubInfo.ConditionExpr[1] == null || nubInfo.IsSameTemp) { nubInfo.CombinedConditionExpr = nubInfo.ConditionExpr[0]; } else { nubInfo.CombinedConditionExpr = NewExprBinop( treeNode, EXPRKIND.BITAND, GetRequiredPredefinedType(PREDEFTYPE.BOOL), nubInfo.ConditionExpr[0], nubInfo.ConditionExpr[1]); } } else { // One of the operands is null so the result will always be null and we // don't need the temps. if (nubInfo.PreExpr[0] != null && nubInfo.PreExpr[0].Kind == EXPRKIND.STTMP) { nubInfo.PreExpr[0] = (nubInfo.PreExpr[0] as EXPRSTTMP).SourceExpr; } if (nubInfo.PreExpr[1] != null && nubInfo.PreExpr[1].Kind == EXPRKIND.STTMP) { nubInfo.PreExpr[1] = (nubInfo.PreExpr[1] as EXPRSTTMP).SourceExpr; } nubInfo.PostExpr[0] = null; nubInfo.PostExpr[1] = null; } nubInfo.IsActive = true; DebugUtil.Assert(nubInfo.CombinedConditionExpr != null || nubInfo.IsAlwaysNull); }
//------------------------------------------------------------ // 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)); }