//------------------------------------------------------------ // CParser.ParseCollectionInitializer // /// <summary></summary> /// <param name="newNode"></param> //------------------------------------------------------------ internal void ParseCollectionInitializer(NEWNODE newNode) { DebugUtil.Assert(CurrentTokenID() == TOKENID.OPENCURLY); NextToken(); UNOPNODE initNode = AllocNode(NODEKIND.COLLECTIONINIT, newNode).AsCOLLECTIONINIT; CListMaker list = new CListMaker(this); int comma = -1; while (CurrentTokenID() != TOKENID.CLOSECURLY) { BASENODE nd = ParseVariableInitializer(initNode, false, -1); if (nd.Kind == NODEKIND.BINOP && nd.Operator == OPERATOR.ASSIGN) { Error(CSCERRID.ERR_InvalidInitializerDeclarator); } else { list.Add(nd, comma); } if (CurrentTokenID() != TOKENID.COMMA) { break; } comma = CurrentTokenIndex(); NextToken(); } Eat(TOKENID.CLOSECURLY); initNode.Operand = list.GetList(initNode); if (initNode.Operand == null) { newNode.InitialNode = null; return; } newNode.InitialNode = initNode; newNode.Flags |= NODEFLAGS.NEW_HAS_COLLECTION_INITIALIZER; if (newNode.ParentNode != null && newNode.ParentNode.Kind == NODEKIND.VARDECL) { VARDECLNODE vdNode = newNode.ParentNode as VARDECLNODE; if (vdNode != null) { newNode.Flags |= NODEFLAGS.NEW_IN_VARDECL; vdNode.NewFlags |= NODEFLAGS.NEW_HAS_COLLECTION_INITIALIZER; } } else if (newNode.ParentNode != null && newNode.ParentNode.Kind == NODEKIND.BINOP && newNode.Operator == OPERATOR.ASSIGN) { VARDECLNODE vdNode = newNode.ParentNode.ParentNode as VARDECLNODE; if (vdNode != null) { newNode.Flags |= NODEFLAGS.NEW_IN_VARDECL; vdNode.NewFlags |= NODEFLAGS.NEW_HAS_COLLECTION_INITIALIZER; } } BASENODE node = newNode.ParentNode; while (node != null && !node.IsStatement) { node = node.ParentNode; } if (node != null) { (node as STATEMENTNODE).NewFlags |= NODEFLAGS.NEW_HAS_COLLECTION_INITIALIZER; } }
//------------------------------------------------------------ // FUNCBREC.BindObjectInitializer // /// <summary></summary> /// <param name="newNode"></param> /// <param name="typeSym"></param> /// <param name="locVarSym"></param> /// <param name="objectExpr"></param> /// <param name="builder"></param> /// <returns></returns> //------------------------------------------------------------ internal EXPR BindObjectInitializer( NEWNODE newNode, TYPESYM typeSym, LOCVARSYM locVarSym, EXPR objectExpr, StatementListBuilder builder) { DebugUtil.Assert(newNode != null && typeSym != null && builder != null); DebugUtil.Assert( (locVarSym != null && objectExpr == null) || (locVarSym == null && objectExpr != null)); BindFlagsEnum bindFlags = BindFlagsEnum.RValueRequired; string localFormat = "<{0}><{1}>__local"; //-------------------------------------------------------- // Bind the local variable. //-------------------------------------------------------- if (locVarSym == null) { string typeName = typeSym.IsAGGTYPESYM ? (typeSym as AGGTYPESYM).GetAggregate().Name : typeSym.Name; string locName = String.Format(localFormat, typeName, (this.localCount)++); locVarSym = Compiler.LocalSymbolManager.CreateLocalSym( SYMKIND.LOCVARSYM, locName, this.currentScopeSym) as LOCVARSYM; locVarSym.TypeSym = typeSym; locVarSym.LocSlotInfo.HasInit = true; locVarSym.DeclTreeNode = newNode; StoreInCache(newNode, locName, locVarSym, null, true); } EXPR locVarExpr = BindToLocal( newNode, locVarSym, bindFlags | BindFlagsEnum.MemberSet); //-------------------------------------------------------- // If objectExpr is not null, assign it to the local variable. //-------------------------------------------------------- if (objectExpr != null) { EXPR assignLocExpr = BindAssignment( newNode, locVarExpr, objectExpr, false); builder.Add(SetNodeStmt(newNode, MakeStmt(newNode, assignLocExpr, 0))); } //-------------------------------------------------------- // Assign each value. //-------------------------------------------------------- DECLSTMTNODE decNode = newNode.InitialNode as DECLSTMTNODE; DebugUtil.Assert(decNode != null); BASENODE node = decNode.VariablesNode; while (node != null) { VARDECLNODE varDecl; if (node.Kind == NODEKIND.LIST) { varDecl = node.AsLIST.Operand1 as VARDECLNODE; node = node.AsLIST.Operand2; } else { varDecl = node as VARDECLNODE; node = null; } BINOPNODE assignNode = varDecl.ArgumentsNode as BINOPNODE; if (assignNode == null || assignNode.Operator != OPERATOR.ASSIGN || assignNode.Operand1 == null || assignNode.Operand1.Kind != NODEKIND.NAME || assignNode.Operand2 == null) { continue; } //---------------------------------------------------- // LHS //---------------------------------------------------- NAMENODE nameNode = assignNode.Operand1 as NAMENODE; DebugUtil.Assert(nameNode != null); bindFlags = BindFlagsEnum.MemberSet; MemberLookup mem = new MemberLookup(); EXPR leftExpr = null; if (mem.Lookup( Compiler, typeSym, locVarExpr, this.parentDeclSym, nameNode.Name, 0, MemLookFlagsEnum.UserCallable)) { SymWithType swt = mem.FirstSymWithType; DebugUtil.Assert(swt != null && swt.IsNotNull); switch (swt.Sym.Kind) { case SYMKIND.MEMBVARSYM: leftExpr = BindToField( assignNode, locVarExpr, FieldWithType.Convert(swt), bindFlags); break; case SYMKIND.PROPSYM: leftExpr = BindToProperty( assignNode, locVarExpr, PropWithType.Convert(swt), bindFlags, null, null); break; default: leftExpr = NewError(nameNode, null); break; } } else { mem.ReportErrors(nameNode); leftExpr = NewError(nameNode, null); } //---------------------------------------------------- // Collection initializer //---------------------------------------------------- if (assignNode.Operand2.Kind == NODEKIND.ARRAYINIT) { if (!leftExpr.TypeSym.IsARRAYSYM) { BindCollectionInitializer( newNode, (assignNode.Operand2 as UNOPNODE).Operand, leftExpr.TypeSym, //typeSym, null, //locVarSym, leftExpr, null, builder); continue; } } //---------------------------------------------------- // RHS //---------------------------------------------------- EXPR rightExpr = BindExpr( assignNode.Operand2, BindFlagsEnum.RValueRequired); //---------------------------------------------------- // Assign //---------------------------------------------------- EXPR assignExpr = BindAssignment( assignNode, leftExpr, rightExpr, false); builder.Add(SetNodeStmt(decNode, MakeStmt(decNode, assignExpr, 0))); } return(locVarExpr); }
//------------------------------------------------------------ // 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)); }
//------------------------------------------------------------ // CAsmLink::SetPEKind (sscli) //------------------------------------------------------------ //virtual internal HRESULT SetPEKind( // mdAssembly AssemblyID, // mdToken FileToken, // DWORD dwPEKind, // DWORD dwMachine) //{ // ASSERT(m_bInited && !m_bAssemblyEmitted && !m_bPreClosed); // ASSERT(AssemblyID == TokenFromRid(mdtAssembly, 1) || AssemblyID == AssemblyIsUBM); // ASSERT((FileToken == AssemblyID) || // (TypeFromToken(FileToken) == mdtFile && RidFromToken(FileToken) < m_pAssem->CountFiles()) || // (TypeFromToken(FileToken) == mdtAssemblyRef && RidFromToken(FileToken) < m_pImports->CountFiles()) || // (TypeFromToken(FileToken) == mdtModule && RidFromToken(FileToken) < m_pModules->CountFiles())); // // HRESULT hr = E_INVALIDARG; // CFile* file = NULL; // // if (TypeFromToken(FileToken) == mdtAssemblyRef) { // hr = m_pImports->GetFile( FileToken, &file); // } else if (TypeFromToken(FileToken) == mdtModule) { // hr = m_pModules->GetFile( FileToken, &file); // } else if (FileToken == AssemblyID) { // file = m_pAssem; // hr = S_OK; // } else if (TypeFromToken(FileToken) == mdtFile) { // if (AssemblyID == AssemblyIsUBM) // m_pAssem->SetPEKind( dwPEKind, dwMachine); // hr = m_pAssem->GetFile( FileToken, &file); // } // // if (SUCCEEDED(hr)) { // file->SetPEKind( dwPEKind, dwMachine); // // DWORD cnt = m_pImports->CountFiles(); // for (DWORD i = 0; i < cnt; i++) { // CFile * ref = NULL; // if (FAILED(hr = m_pImports->GetFile( i, &ref)) || // S_OK != (hr = m_pAssem->ComparePEKind( ref, false))) // return hr; // } // } // // return hr; //} //------------------------------------------------------------ // CAsmLink.ImportTypes //------------------------------------------------------------ // virtual internal HRESULT ImportTypes(mdAssembly AssemblyID, mdToken FileToken, DWORD dwScope, HALINKENUM* phEnum, // IMetaDataImport **ppImportScope, DWORD* pdwCountOfTypes); // virtual internal HRESULT ImportTypes2(mdAssembly AssemblyID, mdToken FileToken, DWORD dwScope, HALINKENUM* phEnum, // IMetaDataImport2 **ppImportScope, DWORD* pdwCountOfTypes); // virtual internal HRESULT EnumCustomAttributes(HALINKENUM hEnum, mdToken tkType, mdCustomAttribute rCustomValues[], // ULONG cMax, ULONG *pcCustomValues); // virtual internal HRESULT EnumImportTypes(HALINKENUM hEnum, DWORD dwMax, mdTypeDef aTypeDefs[], DWORD* pdwCount); // virtual internal HRESULT CloseEnum(HALINKENUM hEnum); // Exporting // virtual internal HRESULT ExportType(mdAssembly AssemblyID, mdToken FileToken, mdTypeDef TypeToken, // LPCWSTR pszTypename, DWORD dwFlags, mdExportedType* pType); // virtual internal HRESULT ExportNestedType(mdAssembly AssemblyID, mdToken FileToken, mdTypeDef TypeToken, // mdExportedType ParentType, LPCWSTR pszTypename, DWORD dwFlags, mdExportedType* pType); //------------------------------------------------------------ // CAsmLink.EmitInternalExportedTypes //------------------------------------------------------------ virtual internal bool EmitInternalExportedTypes() { DebugUtil.Assert(this.inited && !this.assemblyEmitted && !this.preClosed); return(this.assemblyBuilderEx.EmitInternalTypes()); }
//------------------------------------------------------------ // ERRLOC.SetEnd // /// <summary> /// Recursively searches parse-tree for correct right-most node /// </summary> /// <param name="node"></param> //------------------------------------------------------------ internal void SetEnd(BASENODE node) { if (startPos.IsUninitialized) { return; } LEXDATA ld = sourceData.LexData; if (node == null || node.TokenIndex == -1 || ld == null) { return; } SetEndInternal(ld, node); switch (node.Kind) { case NODEKIND.ACCESSOR: // Get and Set always are the token before the '{' SetEndInternal(ld, (node as ACCESSORNODE).OpenCurlyIndex, -1); return; case NODEKIND.ARROW: // BINOPNODE if (node.AsARROW.Operand2 != null) { SetEnd(node.AsARROW.Operand2); } return; case NODEKIND.ATTR: // ATTRNODE if ((node as ATTRNODE).NameNode != null) { SetEnd((node as ATTRNODE).NameNode); } return; case NODEKIND.ATTRDECL: if ((node as ATTRDECLNODE).NameNode != null) { SetEnd((node as ATTRDECLNODE).NameNode); } return; case NODEKIND.ANONBLOCK: if ((node as ANONBLOCKNODE).CloseParenIndex != -1) { // Try to grab the parameters SetEndInternal(ld, (node as ANONBLOCKNODE).CloseParenIndex, 0); // Try to grab the open-curly SetEndInternal(ld, (node as ANONBLOCKNODE).CloseParenIndex, 1); } // And possibly the entire block SetEndInternal( ld, ((node as ANONBLOCKNODE).BodyNode as BLOCKNODE).CloseCurlyIndex, 0); return; case NODEKIND.LAMBDAEXPR: if ((node as LAMBDAEXPRNODE).BodyNode.Kind == NODEKIND.BLOCK) { SetEndInternal( ld, ((node as LAMBDAEXPRNODE).BodyNode as BLOCKNODE).CloseCurlyIndex, 0); } else { SetEnd((node as LAMBDAEXPRNODE).BodyNode); } return; case NODEKIND.CALL: // CALL case NODEKIND.DEREF: SetEndInternal(ld, node.AsANYCALL.CloseParenIndex, 0); return; case NODEKIND.BINOP: // BINOPNODE if ((node as BINOPNODE).Operand2 != null) { SetEnd((node as BINOPNODE).Operand2); } return; case NODEKIND.LIST: SetEnd(node.AsANYBINOP.Operand2); return; case NODEKIND.CLASS: //CLASSNODE case NODEKIND.INTERFACE: case NODEKIND.STRUCT: if (node.AsAGGREGATE.NameNode != null) { SetEnd(node.AsAGGREGATE.NameNode); } return; case NODEKIND.CTOR: case NODEKIND.DTOR: { int i; for (i = node.TokenIndex; i < ld.TokenCount && ld.TokenAt(i).TokenID != TOKENID.IDENTIFIER; i++) { ; } SetEndInternal(ld, i, 0); return; } case NODEKIND.DELEGATE: if ((node as DELEGATENODE).NameNode != null) { SetEnd((node as DELEGATENODE).NameNode); } return; case NODEKIND.DOT: // BINOPNODE if (node.AsDOT.Operand2 != null) { SetEnd(node.AsDOT.Operand2); } return; case NODEKIND.ENUM: if ((node as ENUMNODE).NameNode != null) { SetEnd((node as ENUMNODE).NameNode); } return; case NODEKIND.GENERICNAME: SetEndInternal(ld, (node as GENERICNAMENODE).CloseAngleIndex, 0); return; case NODEKIND.INDEXER: { int i; for (i = node.TokenIndex; i < ld.TokenCount; i++) { SetEndInternal(ld, i, 0); if (ld.TokenAt(i).TokenID == TOKENID.THIS) { break; } } return; } case NODEKIND.METHOD: // METHODNODE // use the name to keep the the same as fields if ((node as METHODNODE).NameNode != null) { SetEnd((node as METHODNODE).NameNode); } return; case NODEKIND.NAMESPACE: // use the name to keep the the same as fields if ((node as NAMESPACENODE).NameNode != null) { SetEnd((node as NAMESPACENODE).NameNode); } return; case NODEKIND.OPERATOR: { int i; for (i = node.TokenIndex; i < ld.TokenCount - 1 && ld.TokenAt(i).TokenID != TOKENID.OPERATOR; i++) { SetEndInternal(ld, i, 0); } SetEndInternal(ld, i, 0); if ((node as OPERATORMETHODNODE).Operator == OPERATOR.IMPLICIT || (node as OPERATORMETHODNODE).Operator == OPERATOR.EXPLICIT) { // for conversion operators the type is the end of the name // (or the token before the open paren) SetEndInternal(ld, (node as OPERATORMETHODNODE).OpenParenIndex, -1); } else { // For non-conversion operators the token after 'operator' // which is the end of the 'name' SetEndInternal(ld, i, 1); } return; } case NODEKIND.NEW: // The type is the most important SetEnd((node as NEWNODE).TypeNode); // But try to get the arguments/array indexes SetEndInternal(ld, (node as NEWNODE).CloseParenIndex, 0); return; case NODEKIND.PROPERTY: if (node.AsANYPROPERTY.NameNode != null) { SetEnd(node.AsANYPROPERTY.NameNode); } return; case NODEKIND.PREDEFINEDTYPE: case NODEKIND.POINTERTYPE: case NODEKIND.NULLABLETYPE: return; case NODEKIND.NAMEDTYPE: SetEnd((node as NAMEDTYPENODE).NameNode); return; case NODEKIND.ARRAYTYPE: // For array types, the token index is the open '['. Add the number of // dimensions and you land on the ']' (1==[], 2==[,], 3==[,,], etc). if ((node as ARRAYTYPENODE).Dimensions == -1) { SetEndInternal(ld, node.TokenIndex, 2); // unknown rank is [?] } else { SetEndInternal(ld, node.TokenIndex, (node as ARRAYTYPENODE).Dimensions); } return; case NODEKIND.UNOP: switch (node.Operator) { case OPERATOR.PAREN: case OPERATOR.PREINC: case OPERATOR.PREDEC: SetEnd((node as UNOPNODE).Operand); break; default: break; } return; case NODEKIND.QUERYEXPR: SetEnd((node as QUERYEXPRNODE).QueryBodyNode); break; case NODEKIND.FROMCLAUSE: case NODEKIND.FROMCLAUSE2: SetEnd((node as FROMCLAUSENODE).ExpressionNode); break; case NODEKIND.LETCLAUSE: SetEnd((node as LETCLAUSENODE).ExpressionNode); break; case NODEKIND.WHERECLAUSE: SetEnd((node as WHERECLAUSENODE).LambdaExpressionNode); break; case NODEKIND.JOINCLAUSE: JOINCLAUSENODE joinNode = node as JOINCLAUSENODE; DebugUtil.Assert(joinNode != null); if (joinNode.IntoNameNode != null) { SetEnd(joinNode.IntoNameNode); } else { if (joinNode.IntoNameNode != null) { SetEnd(joinNode.IntoNameNode); } else { SetEnd(joinNode.EqualRightLambdaExpressionNode); } } break; case NODEKIND.ORDERBYCLAUSE: ORDERBYCLAUSENODE obNode = node as ORDERBYCLAUSENODE; DebugUtil.Assert(obNode != null); if (obNode.LastOrdering != null) { SetEnd(obNode.LastOrdering.LambdaExpressionNode); } else { return; } break; case NODEKIND.SELECTCLAUSE: SetEnd((node as SELECTCLAUSENODE).LambdaExpressionNode); break; case NODEKIND.GROUPCLAUSE: SetEnd((node as GROUPCLAUSENODE).ByExpressionNode); break; case NODEKIND.QUERYCONTINUATION: SetEnd((node as QUERYCONTINUATIONNODE).QueryBodyNode); break; default: break; } }
//------------------------------------------------------------ // FUNCBREC.BindNubConversion // // Called by bindImplicitConversion when the destination type is Nullable<T>. The following // conversions are handled by this method: // // * For S in { object, ValueType, interfaces implemented by underlying type} there is an explicit // unboxing conversion S => T? // * System.Enum => T? there is an unboxing conversion if T is an enum type // * null => T? implemented as default(T?) // // * Implicit T?* => T?+ implemented by either wrapping or calling GetValueOrDefault the // appropriate number of times. // * If imp/exp S => T then imp/exp S => T?+ implemented by converting to T then wrapping the // appropriate number of times. // * If imp/exp S => T then imp/exp S?+ => T?+ implemented by calling GetValueOrDefault (m-1) times // then calling HasValue, producing a null if it returns false, otherwise calling Value, // converting to T then wrapping the appropriate number of times. // // The 3 rules above can be summarized with the following recursive rules: // // * If imp/exp S => T? then imp/exp S? => T? implemented as // qs.HasValue ? (T?)(qs.Value) : default(T?) // * If imp/exp S => T then imp/exp S => T? implemented as new T?((T)s) // // This method also handles calling bindUserDefinedConverion. This method does NOT handle // the following conversions: // // * Implicit boxing conversion from S? to { object, ValueType, Enum, ifaces implemented by S }. (Handled by bindImplicitConversion.) // * If imp/exp S => T then explicit S?+ => T implemented by calling Value the appropriate number // of times. (Handled by bindExplicitConversion.) // // The recursive equivalent is: // // * If imp/exp S => T and T is not nullable then explicit S? => T implemented as qs.Value // // Some nullable conversion are NOT standard conversions. In particular, if S => T is implicit // then S? => T is not standard. Similarly if S => T is not implicit then S => T? is not standard. // /// <summary></summary> /// <param name="treeNode"></param> /// <param name="srcExpr"></param> /// <param name="srcTypeSym"></param> /// <param name="dstNubSym"></param> /// <param name="dstExpr"></param> /// <param name="flags"></param> /// <returns></returns> //------------------------------------------------------------ private bool BindNubConversion( BASENODE treeNode, EXPR srcExpr, TYPESYM srcTypeSym, NUBSYM dstNubSym, ref EXPR dstExpr, ConvertTypeEnum flags) { // This code assumes that STANDARD and ISEXPLICIT are never both set. // bindUserDefinedConversion should ensure this! DebugUtil.Assert((~flags & (ConvertTypeEnum.STANDARD | ConvertTypeEnum.ISEXPLICIT)) != 0); DebugUtil.Assert(srcExpr == null || srcExpr.TypeSym == srcTypeSym); DebugUtil.Assert(dstExpr == null || srcExpr != null); DebugUtil.Assert(srcTypeSym != dstNubSym); // bindImplicitConversion should have taken care of this already. AGGTYPESYM dstAggTypeSym = dstNubSym.GetAggTypeSym(); if (dstAggTypeSym == null) { return(false); } // Check for the unboxing conversion. This takes precedence over the wrapping conversions. if (Compiler.IsBaseType(dstNubSym.BaseTypeSym, srcTypeSym) && !FWrappingConv(srcTypeSym, dstNubSym)) { // These should be different! Fix the caller if srcTypeSym is an AGGTYPESYM of Nullable. DebugUtil.Assert(dstAggTypeSym != srcTypeSym); // srcTypeSym is a base type of the destination nullable type so there is an explicit // unboxing conversion. if ((flags & ConvertTypeEnum.ISEXPLICIT) == 0) { return(false); } return(BindSimpleCast(treeNode, srcExpr, dstNubSym, ref dstExpr, EXPRFLAG.UNBOX)); } int dstNubStripCount; int srcNubStripCount; TYPESYM dstBaseTypeSym = dstNubSym.StripNubs(out dstNubStripCount); TYPESYM srcBaseTypeSym = srcTypeSym.StripNubs(out srcNubStripCount); bindNubConversion_Convert fnConvert; EXPR expr = null; // temp if ((flags & ConvertTypeEnum.ISEXPLICIT) != 0) { fnConvert = new bindNubConversion_Convert(BindExplicitConversion); } else { fnConvert = new bindNubConversion_Convert(BindImplicitConversion); } //bool (FUNCBREC::*pfn)(BASENODE *, EXPR *, TYPESYM *, TYPESYM *, EXPR **, uint) = // (flags & ISEXPLICIT) ? &FUNCBREC::bindExplicitConversion : &FUNCBREC::bindImplicitConversion; if (srcNubStripCount == 0) { DebugUtil.Assert(srcTypeSym == srcBaseTypeSym); // The null type can be implicitly converted to T? as the default value. if (srcTypeSym.IsNULLSYM) { dstExpr = AddSideEffects(treeNode, NewExprZero(treeNode, dstNubSym), srcExpr, true, true); return(true); } EXPR tempExpr = srcExpr; // If there is an implicit/explicit S => T then there is an implicit/explicit S => T? if (srcTypeSym == dstBaseTypeSym || fnConvert( treeNode, srcExpr, srcTypeSym, dstBaseTypeSym, ref tempExpr, flags | ConvertTypeEnum.NOUDC)) { // srcTypeSym is not nullable so just wrap the required number of times. for (int i = 0; i < dstNubStripCount; i++) { tempExpr = BindNubNew(treeNode, tempExpr); } DebugUtil.Assert(tempExpr.TypeSym == dstNubSym); dstExpr = tempExpr; return(true); } // No builtin conversion. Maybe there is a user defined conversion.... return( (flags & ConvertTypeEnum.NOUDC) == 0 && BindUserDefinedConversion( treeNode, srcExpr, srcTypeSym, dstNubSym, ref dstExpr, (flags & ConvertTypeEnum.ISEXPLICIT) == 0)); } // Both are Nullable so there is only a conversion if there is a conversion between the base types. // That is, if there is an implicit/explicit S => T then there is an implicit/explicit S?+ => T?+. if (srcBaseTypeSym != dstBaseTypeSym && !fnConvert(treeNode, null, srcBaseTypeSym, dstBaseTypeSym, ref expr, flags | ConvertTypeEnum.NOUDC)) { // No builtin conversion. Maybe there is a user defined conversion.... return( (flags & ConvertTypeEnum.NOUDC) == 0 && BindUserDefinedConversion( treeNode, srcExpr, srcTypeSym, dstNubSym, ref dstExpr, (flags & ConvertTypeEnum.ISEXPLICIT) == 0)); } // We need to go all the way down to the base types, do the conversion, then come all the way back up. EXPR valExpr; NubInfo nubInfo = new NubInfo(); BindNubCondValBin( treeNode, srcExpr, null, ref nubInfo, LiftFlagsEnum.LiftBoth); valExpr = nubInfo.Val(0); DebugUtil.Assert(valExpr.TypeSym == srcBaseTypeSym); if (!fnConvert( treeNode, valExpr, valExpr.TypeSym, dstBaseTypeSym, ref valExpr, flags | ConvertTypeEnum.NOUDC)) { DebugUtil.Assert(false, "bind(Im|Ex)plicitConversion failed unexpectedly"); return(false); } for (int i = 0; i < dstNubStripCount; i++) { valExpr = BindNubNew(treeNode, valExpr); } DebugUtil.Assert(valExpr.TypeSym == dstNubSym); dstExpr = BindNubOpRes(treeNode, dstNubSym, dstNubSym, valExpr, ref nubInfo, false); return(true); }
//------------------------------------------------------------ // ConsoleOutput.WriteLine (3) // /// <summary></summary> /// <param name="fmt"></param> /// <param name="args"></param> //------------------------------------------------------------ internal void WriteLine(string fmt, params Object[] args) { DebugUtil.Assert(this.consoleObject != null); this.consoleObject.WriteLine(this.FormatString(fmt, args)); }
//------------------------------------------------------------ // FUNCBREC.HasIEnumerable (2) // /// <summary> /// Rewrite HasIEnumerable for collection initializer. /// Return the IEnumerable or IEnumerable<T> instance. /// </summary> /// <param name="collection"></param> /// <param name="tree"></param> /// <param name="badType"></param> /// <param name="badMember"></param> /// <returns></returns> //------------------------------------------------------------ private AGGTYPESYM HasIEnumerable( TYPESYM collectionTypeSym/*, * BASENODE treeNode, * TYPESYM badTypeSym, * PREDEFNAME badMemberName*/ ) { AGGTYPESYM ifaceCandidateAts = null; // First try the generic interfaces AGGSYM gEnumAggSym = Compiler.GetOptPredefAgg(PREDEFTYPE.G_IENUMERABLE, true); TypeArray allIfacesTypeArray = null; AGGTYPESYM baseAts = null; // If generics don't exist or the type isn't an AGGTYPESYM // then we can't check the interfaces (and base-class interfaces) // for IEnumerable<T> so immediately try the non-generic IEnumerable if (gEnumAggSym == null) { goto NO_GENERIC; } if (collectionTypeSym.IsAGGTYPESYM) { if (collectionTypeSym.GetAggregate() == gEnumAggSym || collectionTypeSym.IsPredefType(PREDEFTYPE.IENUMERABLE)) { DebugUtil.Assert(false, "IEnumerable/ator types are bad!"); goto LERROR; } AGGTYPESYM tempAts = collectionTypeSym as AGGTYPESYM; allIfacesTypeArray = tempAts.GetIfacesAll(); baseAts = tempAts.GetBaseClass(); } else if (collectionTypeSym.IsTYVARSYM) { // Note: // we'll search the interface list before the class constraint, // but it doesn't matter since we require a unique instantiation of IEnumerable<T>. // Note: // The pattern search will usually find the interface constraint // - but if the class constraint has a non-public or non-applicable // or non-method GetEnumerator, // the interfaces are hidden in which case we will find them here. TYVARSYM tempTvSym = collectionTypeSym as TYVARSYM; allIfacesTypeArray = tempTvSym.AllInterfaces; baseAts = tempTvSym.BaseClassSym; } else { goto NO_GENERIC; } DebugUtil.Assert(allIfacesTypeArray != null); // If the type implements exactly one instantiation of // IEnumerable<T> then it's the one. // // If it implements none then try the non-generic interface. // // If it implements more than one, then it's an error. // // Search the direct and indirect interfaces via allIfacesTypeArray, // going up the base chain... // Work up the base chain for (; ;) { // Now work across all the interfaces for (int i = 0; i < allIfacesTypeArray.Count; ++i) { AGGTYPESYM iface = allIfacesTypeArray[i] as AGGTYPESYM; if (iface.GetAggregate() == gEnumAggSym) { if (ifaceCandidateAts == null) { // First implementation ifaceCandidateAts = iface; } else if (iface != ifaceCandidateAts) { // If this really is a different instantiation report an error Compiler.Error( treeNode, CSCERRID.ERR_MultipleIEnumOfT, new ErrArgRef(collectionTypeSym), new ErrArg(gEnumAggSym.GetThisType())); return(null); } } } // Check the base class. if (baseAts == null) { break; } allIfacesTypeArray = baseAts.GetIfacesAll(); baseAts = baseAts.GetBaseClass(); } // Report the one and only generic interface if (ifaceCandidateAts != null) { DebugUtil.Assert( CanConvert(collectionTypeSym, ifaceCandidateAts, ConvertTypeEnum.NOUDC)); return(ifaceCandidateAts); } NO_GENERIC: if (collectionTypeSym.IsPredefType(PREDEFTYPE.IENUMERABLE)) { DebugUtil.VsFail("Why didn't IEnumerator match the pattern?"); goto LERROR; } // No errors, no generic interfaces, try the non-generic interface ifaceCandidateAts = GetRequiredPredefinedType(PREDEFTYPE.IENUMERABLE); if (CanConvert(collectionTypeSym, ifaceCandidateAts, ConvertTypeEnum.NOUDC)) { return(ifaceCandidateAts); } LERROR: return(null); }
//------------------------------------------------------------ // CSConsoleArgs.ExpandResponseFiles // /// <summary> /// <para>(ConsoleArgs::ProcessResponseArgs in sscli.)</para> /// <para>Process Response files on the command line /// Returns true if it allocated a new argv array that must be freed later</para> /// <para>コマンドラインでレスポンスファイルが指定されていたら、 /// その内容をオプションリストに追加する。 /// (レスポンスファイルは @ファイル名 の形式で指定されている。)</para> /// </summary> //------------------------------------------------------------ private void ExpandResponseFiles() { Dictionary <string, bool> processedResponseFiles = new Dictionary <string, bool>(new StringEqualityComparerIgnoreCase()); List <string[]> listTemp = null; string fileName = null; string fullName = null; string fileContents = null; Exception excp = null; bool foundResponseFile; int loopCount = 0; const int maxLoopCount = 32; do { if (loopCount >= maxLoopCount) { throw new Exception("Too many nested response file."); } listTemp = new List <string[]>(); foundResponseFile = false; foreach (string[] opt in this.OptionList) { // オプションが null や空の場合は破棄する。 if (opt == null || opt.Length == 0) { continue; } // 1 文字目が @ でないものはそのままリストに追加する。 if (opt[1] != "@") { listTemp.Add(opt); continue; } if (opt.Length <= 2 || String.IsNullOrEmpty(opt[2])) { this.Controller.ReportError( CSCERRID.ERR_NoFileSpec, ERRORKIND.ERROR, opt[0]); continue; } // Check for duplicates // @ と引用符を外す。 fileName = opt[2]; IOUtil.RemoveQuotes(ref fileName); if (String.IsNullOrEmpty(fileName)) { this.Controller.ReportError( CSCERRID.ERR_NoFileSpec, ERRORKIND.ERROR, opt[0]); continue; } // ファイルのフルパスを求める。 fullName = this.GetFullFileName(fileName, false); if (String.IsNullOrEmpty(fullName)) { this.Controller.ReportError( CSCERRID.ERR_NoFileSpec, ERRORKIND.ERROR, opt[0]); continue; } // 得られたファイルがすでに処理されていないか調べる。 try { if (processedResponseFiles.ContainsKey(fullName)) { continue; } } catch (ArgumentException) { DebugUtil.Assert(false); continue; } // ファイルの内容を読み込む。エラーの場合はメッセージを表示して次へ。 if (!IOUtil.ReadTextFile(fullName, null, out fileContents, out excp)) { this.Controller.ReportError(ERRORKIND.ERROR, excp.Message); continue; } // レスポンスファイル内で指定されているオプションを取得する。 TextToArgs(fileContents, listTemp); foundResponseFile = true; // 処理済みファイルのリストに追加する。 processedResponseFiles.Add(fullName, true); } this.OptionList = listTemp; ++loopCount; } while (foundResponseFile); }
//------------------------------------------------------------ // ConsoleOutput.WriteLine (1) // /// <summary> /// <para>Output an empty line.</para> /// <para>(PrintBlankLine in sscli)</para> /// </summary> //------------------------------------------------------------ internal void WriteLine() { DebugUtil.Assert(this.consoleObject != null); this.consoleObject.WriteLine(); }
//------------------------------------------------------------ // FUNCBREC.OperatorToExpressionType // /// <summary></summary> /// <param name="op"></param> /// <returns></returns> //------------------------------------------------------------ internal ExpressionType OperatorToExpressionType(OPERATOR op) { switch (op) { case OPERATOR.NONE: //return ExpressionType; break; case OPERATOR.ASSIGN: return(ExpressionType.Assign); case OPERATOR.ADDEQ: return(ExpressionType.AddAssign); case OPERATOR.SUBEQ: return(ExpressionType.SubtractAssign); case OPERATOR.MULEQ: return(ExpressionType.MultiplyAssign); case OPERATOR.DIVEQ: return(ExpressionType.DivideAssign); case OPERATOR.MODEQ: return(ExpressionType.ModuloAssign); case OPERATOR.ANDEQ: return(ExpressionType.AndAssign); case OPERATOR.XOREQ: return(ExpressionType.ExclusiveOrAssign); case OPERATOR.OREQ: return(ExpressionType.OrAssign); case OPERATOR.LSHIFTEQ: return(ExpressionType.LeftShiftAssign); case OPERATOR.RSHIFTEQ: return(ExpressionType.RightShiftAssign); case OPERATOR.QUESTION: //return ExpressionType; break; case OPERATOR.VALORDEF: //return ExpressionType; break; case OPERATOR.LOGOR: return(ExpressionType.Or); case OPERATOR.LOGAND: return(ExpressionType.And); case OPERATOR.BITOR: //return ExpressionType; case OPERATOR.BITXOR: //return ExpressionType; case OPERATOR.BITAND: //return ExpressionType; break; case OPERATOR.EQ: return(ExpressionType.Equal); case OPERATOR.NEQ: return(ExpressionType.NotEqual); case OPERATOR.LT: return(ExpressionType.LessThan); case OPERATOR.LE: return(ExpressionType.LessThanOrEqual); case OPERATOR.GT: return(ExpressionType.GreaterThan); case OPERATOR.GE: return(ExpressionType.GreaterThanOrEqual); case OPERATOR.IS: return(ExpressionType.TypeIs); case OPERATOR.AS: return(ExpressionType.TypeAs); case OPERATOR.LSHIFT: return(ExpressionType.LeftShift); case OPERATOR.RSHIFT: return(ExpressionType.RightShift); case OPERATOR.ADD: return(ExpressionType.Add); case OPERATOR.SUB: return(ExpressionType.Subtract); case OPERATOR.MUL: return(ExpressionType.Multiply); case OPERATOR.DIV: return(ExpressionType.Divide); case OPERATOR.MOD: return(ExpressionType.Modulo); case OPERATOR.NOP: //return ExpressionType; break; case OPERATOR.UPLUS: return(ExpressionType.UnaryPlus); case OPERATOR.NEG: return(ExpressionType.Negate); case OPERATOR.BITNOT: return(ExpressionType.OnesComplement); case OPERATOR.LOGNOT: return(ExpressionType.Not); case OPERATOR.PREINC: return(ExpressionType.PreIncrementAssign); case OPERATOR.PREDEC: return(ExpressionType.PreDecrementAssign); case OPERATOR.TYPEOF: //return ExpressionType; case OPERATOR.SIZEOF: //return ExpressionType; case OPERATOR.CHECKED: //return ExpressionType; case OPERATOR.UNCHECKED: //return ExpressionType; case OPERATOR.MAKEREFANY: //return ExpressionType; case OPERATOR.REFVALUE: //return ExpressionType; case OPERATOR.REFTYPE: //return ExpressionType; case OPERATOR.ARGS: //return ExpressionType; case OPERATOR.CAST: //return ExpressionType; case OPERATOR.INDIR: //return ExpressionType; case OPERATOR.ADDR: //return ExpressionType; case OPERATOR.COLON: //return ExpressionType; case OPERATOR.THIS: //return ExpressionType; case OPERATOR.BASE: //return ExpressionType; case OPERATOR.NULL: //return ExpressionType; case OPERATOR.TRUE: //return ExpressionType; case OPERATOR.FALSE: //return ExpressionType; case OPERATOR.CALL: //return ExpressionType; case OPERATOR.DEREF: //return ExpressionType; case OPERATOR.PAREN: //return ExpressionType; break; case OPERATOR.POSTINC: return(ExpressionType.PostIncrementAssign); case OPERATOR.POSTDEC: return(ExpressionType.PostDecrementAssign); case OPERATOR.DOT: //return ExpressionType; case OPERATOR.IMPLICIT: //return ExpressionType; case OPERATOR.EXPLICIT: //return ExpressionType; case OPERATOR.EQUALS: //return ExpressionType; case OPERATOR.COMPARE: //return ExpressionType; case OPERATOR.DEFAULT: //return ExpressionType; break; // CS3 case OPERATOR.LAMBDA: return(ExpressionType.Lambda); default: break; } DebugUtil.Assert(false); return((ExpressionType)(-1)); }
private bool dontDoHashes = false; // m_bDontDoHashes : 1; //------------------------------------------------------------ // CAsmLink Constructor // /// <summary></summary> /// <param name="cntr"></param> //------------------------------------------------------------ internal CAsmLink(CController cntr) { DebugUtil.Assert(cntr != null); this.controller = cntr; }
//------------------------------------------------------------ // CAsmLink.PreCloseAssembly //------------------------------------------------------------ virtual internal bool PreCloseAssembly(uint AssemblyID) { DebugUtil.Assert(this.inited && !this.preClosed); return(true); }
//------------------------------------------------------------ // CParser.ParseObjectInitializer // /// <summary></summary> /// <param name="newNode"></param> //------------------------------------------------------------ internal void ParseObjectInitializer(NEWNODE newNode) { DebugUtil.Assert(CurrentTokenID() == TOKENID.OPENCURLY); NextToken(); DECLSTMTNODE stmtNode = AllocNode(NODEKIND.DECLSTMT, newNode) as DECLSTMTNODE; CListMaker list = new CListMaker(this); int comma = -1; while ( CurrentTokenID() != TOKENID.CLOSECURLY && CurrentTokenID() != TOKENID.ENDFILE) { if (CurrentTokenID() == TOKENID.IDENTIFIER && PeekToken(1) == TOKENID.EQUAL) { list.Add( ParseVariableDeclarator( stmtNode, stmtNode, (uint)PARSEDECLFLAGS.LOCAL, false, // isFirst, -1), comma); } else { Error(CSCERRID.ERR_InvalidInitializerDeclarator); TOKENID tid = CurrentTokenID(); while ( tid != TOKENID.COMMA && tid != TOKENID.CLOSECURLY && tid != TOKENID.ENDFILE) { NextToken(); tid = CurrentTokenID(); } } if (CurrentTokenID() != TOKENID.COMMA) { break; } comma = CurrentTokenIndex(); NextToken(); } Eat(TOKENID.CLOSECURLY); stmtNode.VariablesNode = list.GetList(stmtNode); newNode.InitialNode = stmtNode; newNode.Flags |= NODEFLAGS.NEW_HAS_OBJECT_INITIALIZER; if (newNode.ParentNode != null && newNode.ParentNode.Kind == NODEKIND.VARDECL) { VARDECLNODE vdNode = newNode.ParentNode as VARDECLNODE; if (vdNode != null) { newNode.Flags |= NODEFLAGS.NEW_IN_VARDECL; vdNode.NewFlags |= NODEFLAGS.NEW_HAS_OBJECT_INITIALIZER; } } else if (newNode.ParentNode != null && newNode.ParentNode.Kind == NODEKIND.BINOP && newNode.Operator == OPERATOR.ASSIGN) { VARDECLNODE vdNode = newNode.ParentNode.ParentNode as VARDECLNODE; if (vdNode != null) { newNode.Flags |= NODEFLAGS.NEW_IN_VARDECL; vdNode.NewFlags |= NODEFLAGS.NEW_HAS_OBJECT_INITIALIZER; } } BASENODE node = newNode.ParentNode; while (node != null && !node.IsStatement) { node = node.ParentNode; } if (node != null) { (node as STATEMENTNODE).NewFlags |= NODEFLAGS.NEW_HAS_OBJECT_INITIALIZER; } }
//------------------------------------------------------------ // ConsoleOutput.PrettyPrint (2) // /// <summary></summary> /// <param name="builder"></param> /// <param name="text"></param> /// <param name="indent"></param> //------------------------------------------------------------ protected void PrettyPrint( StringBuilder builder, string text, int indent) { // 100 characters should be more than large enough for any indent DebugUtil.Assert(indent >= 0 && indent <= 100); if (String.IsNullOrEmpty(text)) { return; } int width = this.ConsoleWidth - indent - 1; if (width <= 0) { builder.Append(text); return; } // the first line int count = indent; if (builder.Length >= indent) { builder.Append(System.Environment.NewLine); builder.Append(' ', count); } else { count -= builder.Length; builder.Append(' ', count); } if (text.Length <= width) { builder.Append(text); builder.Append(System.Environment.NewLine); return; } builder.Append(text.Substring(0, width)); builder.Append(System.Environment.NewLine); text = text.Substring(width); while (true) { builder.Append(' ', indent); if (text.Length <= width) { builder.Append(text); builder.Append(System.Environment.NewLine); return; } builder.Append(text.Substring(0, width)); builder.Append(System.Environment.NewLine); text = text.Substring(width); } }
//------------------------------------------------------------ // FUNCBREC.BindCollectionInitializer // /// <summary></summary> /// <param name="newNode"></param> /// <param name="typeSym"></param> /// <param name="locVarSym"></param> /// <param name="objectExpr"></param> /// <param name="builder"></param> /// <returns></returns> //------------------------------------------------------------ internal EXPR BindCollectionInitializer( NEWNODE newNode, BASENODE elementsNode, TYPESYM typeSym, LOCVARSYM locVarSym, EXPR leftExpr, EXPR rightExpr, StatementListBuilder builder) { DebugUtil.Assert(newNode != null && typeSym != null && builder != null); DebugUtil.Assert(locVarSym != null || leftExpr != null || rightExpr != null); string addMethName = Compiler.NameManager.GetPredefinedName(PREDEFNAME.ADD); //-------------------------------------------------------- // typeSym should implement IEnumerable. //-------------------------------------------------------- AGGTYPESYM enumerableSym = HasIEnumerable(typeSym); if (enumerableSym == null) { Compiler.Error( newNode.TypeNode, CSCERRID.ERR_CollectInitRequiresIEnumerable, new ErrArg(typeSym)); return(rightExpr); } TYPESYM paramTypeSym = null; TypeArray typeArgs = enumerableSym.TypeArguments; if (typeArgs != null && typeArgs.Count > 0) { DebugUtil.Assert(typeArgs.Count == 1); paramTypeSym = typeArgs[0]; } else { paramTypeSym = Compiler.GetReqPredefAgg(PREDEFTYPE.OBJECT, true).GetThisType(); if (typeArgs == null) { typeArgs = new TypeArray(); } typeArgs.Add(paramTypeSym); typeArgs = Compiler.MainSymbolManager.AllocParams(typeArgs); } BindFlagsEnum bindFlags = BindFlagsEnum.RValueRequired; string localFormat = "<{0}><{1}>__local"; //-------------------------------------------------------- // Bind the local variable. //-------------------------------------------------------- if (leftExpr == null) { if (locVarSym == null) { string locName = String.Format(localFormat, typeSym.Name, (this.localCount)++); locVarSym = Compiler.LocalSymbolManager.CreateLocalSym( SYMKIND.LOCVARSYM, locName, this.currentScopeSym) as LOCVARSYM; locVarSym.TypeSym = typeSym; locVarSym.LocSlotInfo.HasInit = true; locVarSym.DeclTreeNode = newNode; StoreInCache(newNode, locName, locVarSym, null, true); } leftExpr = BindToLocal( newNode, locVarSym, bindFlags | BindFlagsEnum.MemberSet); } //-------------------------------------------------------- // If objectExpr is not null, assign it to the local variable. //-------------------------------------------------------- if (rightExpr != null) { EXPR assignLocExpr = BindAssignment( newNode, leftExpr, rightExpr, false); builder.Add(SetNodeStmt(newNode, MakeStmt(newNode, assignLocExpr, 0))); } //-------------------------------------------------------- // Get "Add" method. //-------------------------------------------------------- MemberLookup mem = new MemberLookup(); if (!mem.Lookup( Compiler, typeSym, leftExpr, this.parentDeclSym, addMethName, 0, MemLookFlagsEnum.UserCallable)) { Compiler.Error( newNode.TypeNode, CSCERRID.ERR_NoSuchMember, new ErrArg(typeSym), new ErrArg("Add")); return(NewError(newNode, null)); } if (mem.FirstSym == null || !mem.FirstSym.IsMETHSYM) { return(NewError(newNode, null)); } TypeArray typeGroup = mem.GetAllTypes(); EXPRMEMGRP grpExpr = NewExpr( newNode, EXPRKIND.MEMGRP, Compiler.MainSymbolManager.MethodGroupTypeSym) as EXPRMEMGRP; grpExpr.Name = addMethName; grpExpr.SymKind = SYMKIND.METHSYM; grpExpr.TypeArguments = BSYMMGR.EmptyTypeArray; grpExpr.ParentTypeSym = typeSym; grpExpr.MethPropSym = null; grpExpr.ObjectExpr = leftExpr; grpExpr.ContainingTypeArray = typeGroup; grpExpr.Flags |= EXPRFLAG.USERCALLABLE; //-------------------------------------------------------- // Add each value. //-------------------------------------------------------- DebugUtil.Assert(newNode.InitialNode != null); #if false BASENODE node = null; switch (newNode.InitialNode.Kind) { case NODEKIND.DECLSTMT: node = (newNode.InitialNode as DECLSTMTNODE).VariablesNode; break; case NODEKIND.UNOP: node = (newNode.InitialNode as UNOPNODE).Operand; break; default: DebugUtil.Assert(false); break; } #endif BASENODE node = elementsNode; while (node != null) { BASENODE elementNode; if (node.Kind == NODEKIND.LIST) { elementNode = node.AsLIST.Operand1; node = node.AsLIST.Operand2; } else { elementNode = node; node = null; } //---------------------------------------------------- // Bind the elements //---------------------------------------------------- EXPR elementExpr = BindExpr( elementNode, BindFlagsEnum.RValueRequired); //---------------------------------------------------- // Add the elements //---------------------------------------------------- EXPR addExpr = BindGrpToArgs(newNode, bindFlags, grpExpr, elementExpr); if (addExpr != null) { builder.Add(SetNodeStmt(newNode, MakeStmt(newNode, addExpr, 0))); } } return(leftExpr); }
//------------------------------------------------------------ // FUNCBREC.CreateAutoImplementedSetAccessor // /// <summary></summary> /// <param name="methodSym"></param> /// <returns></returns> //------------------------------------------------------------ internal EXPR CreateAutoImplementedSetAccessor(METHSYM methodSym) { CreateNewScope(); SCOPESYM scopeSym = this.currentScopeSym; this.currentScopeSym.ScopeFlags = SCOPEFLAGS.NONE; this.currentBlockExpr = NewExprBlock(treeNode); this.currentBlockExpr.ScopeSym = this.currentScopeSym; //-------------------------------------------------------- // Back filed //-------------------------------------------------------- SymWithType fieldSwt = new SymWithType(); AGGTYPESYM parentAts = methodSym.ParentAggSym.GetThisType(); fieldSwt.Set( methodSym.PropertySym.BackFieldSym, parentAts); EXPR fieldExpr = BindToField( null, BindThisImplicit(null), FieldWithType.Convert(fieldSwt), BindFlagsEnum.RValueRequired); //-------------------------------------------------------- // Parameter "value" //-------------------------------------------------------- // The SYM instance of parameter "value" is a LOCVARSYM instance, // and is created in CLSDREC.FillMethInfoCommon. LOCVARSYM locSym = Compiler.LocalSymbolManager.LookupLocalSym( Compiler.NameManager.GetPredefinedName(PREDEFNAME.VALUE), this.OuterScopeSym, SYMBMASK.LOCVARSYM) as LOCVARSYM; DebugUtil.Assert(locSym != null); SymWithType valueSwt = new SymWithType(); valueSwt.Set(locSym, null); EXPR valueExpr = BindToLocal(null, locSym, BindFlagsEnum.RValueRequired); //-------------------------------------------------------- // BackField = value //-------------------------------------------------------- EXPR assignExpr = NewExprBinop( null, EXPRKIND.ASSG, fieldExpr.TypeSym, fieldExpr, valueExpr); //-------------------------------------------------------- // Statement //-------------------------------------------------------- EXPRSTMTAS stmt = NewExpr(null, EXPRKIND.STMTAS, null) as EXPRSTMTAS; stmt.Expr = assignExpr; //-------------------------------------------------------- // Block //-------------------------------------------------------- this.currentBlockExpr.StatementsExpr = stmt; EXPRBLOCK blockExpr = this.currentBlockExpr; this.currentBlockExpr = blockExpr.OwingBlockExpr; CloseScope(); CorrectAnonMethScope(blockExpr.ScopeSym); return(blockExpr); }
//------------------------------------------------------------ // ERRLOC.SetEndInternal (1) // /// <summary> /// only set the end if it is on the same line /// as we want to report the error on /// </summary> /// <param name="ld"></param> /// <param name="node"></param> //------------------------------------------------------------ private void SetEndInternal(LEXDATA ld, BASENODE node) { DebugUtil.Assert(!startPos.IsUninitialized); SetEndInternal(ld, (int)node.TokenIndex, 0); }
//------------------------------------------------------------ // SecurityUtil.AppendSecurityAttribute (2) // /// <summary> /// /// </summary> /// <param name="secAttrType"></param> /// <param name="positionalArgs"></param> /// <param name="argNames"></param> /// <param name="argValues"></param> /// <param name="permissionSets"></param> /// <param name="excp"></param> /// <returns></returns> //------------------------------------------------------------ public static bool AppendSecurityAttribute( Type secAttrType, Object[] positionalArgs, List <string> fieldNames, List <object> fieldValues, List <string> propertyNames, List <object> propertyValues, Dictionary <SecurityAction, PermissionSet> permissionSets, out Exception excp) { excp = null; if (permissionSets == null) { return(false); } if (secAttrType == null || positionalArgs == null || positionalArgs.Length == 0) { return(false); } int fieldCount = fieldNames != null ? fieldNames.Count : 0; if (fieldCount != (fieldValues != null ? fieldValues.Count : 0)) { return(false); } int propertyCount = propertyNames != null ? propertyNames.Count : 0; if (propertyCount != (propertyValues != null ? propertyValues.Count : 0)) { return(false); } SecurityAction secAction; try { secAction = (SecurityAction)positionalArgs[0]; } catch (InvalidCastException ex) { excp = ex; return(false); } //switch (secAction) //{ // case SecurityAction.Assert: // case SecurityAction.Demand: // case SecurityAction.Deny: // case SecurityAction.InheritanceDemand: // case SecurityAction.LinkDemand: // case SecurityAction.PermitOnly: // case SecurityAction.RequestMinimum: // case SecurityAction.RequestOptional: // case SecurityAction.RequestRefuse: // break; // default: // return false; //} // Create the attribute instance with its positional arguments Object activatedObj = ReflectionUtil.CreateInstance( secAttrType, positionalArgs, out excp); if (activatedObj == null || excp != null) { return(false); } // Assign the named arguments to the fields. Object[] narg = new Object[1]; if (fieldCount > 0) { for (int i = 0; i < fieldCount; ++i) { narg[0] = fieldValues[i]; if (!ReflectionUtil.InvokeMember( secAttrType, fieldNames[i], BindingFlags.SetField, null, activatedObj, narg, out excp)) { return(false); } } } // Assign the named arguments to the properties. if (propertyCount > 0) { for (int i = 0; i < propertyCount; ++i) { narg[0] = propertyValues[i]; if (!ReflectionUtil.InvokeMember( secAttrType, propertyNames[i], BindingFlags.SetProperty, null, activatedObj, narg, out excp)) { return(false); } } } SecurityAttribute secAttr = activatedObj as SecurityAttribute; if (secAttr == null) { return(false); } IPermission secPerm = secAttr.CreatePermission(); if (secAttr != null) { PermissionSet permSet = null; if (!permissionSets.TryGetValue(secAction, out permSet)) { permSet = new PermissionSet(null); permissionSets.Add(secAction, permSet); } else if (permSet == null) { permSet = new PermissionSet(null); permissionSets[secAction] = permSet; } DebugUtil.Assert(permSet != null); permSet.AddPermission(secPerm); return(true); } return(false); }
//------------------------------------------------------------ // CSourceData Constructor (private) // /// <summary> /// This is private. Call CreateInstance method to create an instance. /// </summary> /// <param name="module"></param> //------------------------------------------------------------ private CSourceData(CSourceModuleBase module) { DebugUtil.Assert(module != null); sourceModuleBase = module; }
//------------------------------------------------------------ // SecurityUtil.AppendSecurityAttribute (1) // /// <summary> /// /// </summary> /// <param name="secAttrType"></param> /// <param name="positionalArgs"></param> /// <param name="argNames"></param> /// <param name="argValues"></param> /// <param name="permissionSets"></param> /// <param name="excp"></param> /// <returns></returns> //------------------------------------------------------------ public static bool AppendSecurityAttribute( Type secAttrType, Object[] positionalArgs, String[] argNames, Object[] argValues, Dictionary <SecurityAction, PermissionSet> permissionSets, out Exception excp) { excp = null; if (permissionSets == null) { return(false); } if (secAttrType == null || positionalArgs == null || positionalArgs.Length == 0) { return(false); } SecurityAction secAction; try { secAction = (SecurityAction)positionalArgs[0]; } catch (InvalidCastException ex) { excp = ex; return(false); } //switch (secAction) //{ // case SecurityAction.Assert: // case SecurityAction.Demand: // case SecurityAction.Deny: // case SecurityAction.InheritanceDemand: // case SecurityAction.LinkDemand: // case SecurityAction.PermitOnly: // case SecurityAction.RequestMinimum: // case SecurityAction.RequestOptional: // case SecurityAction.RequestRefuse: // break; // default: // return false; //} // Create the attribute instance with its positional arguments Object activatedObj = ReflectionUtil.CreateInstance( secAttrType, positionalArgs, out excp); if (activatedObj == null || excp != null) { return(false); } // Assign the named arguments to the fields or properties. int namedCount = 0; if (argNames != null && (namedCount = argNames.Length) > 0) { if (argValues == null || argValues.Length != namedCount) { return(false); } Object[] narg = new Object[1]; for (int i = 0; i < argNames.Length; ++i) { string name = argNames[i]; if (String.IsNullOrEmpty(name)) { return(false); } MemberInfo[] membs = secAttrType.GetMember(name); if (membs.Length != 1) { return(false); } narg[0] = argValues[i]; MemberTypes membType = membs[0].MemberType; BindingFlags bindFlags = 0; if (membType == MemberTypes.Property) { bindFlags = BindingFlags.SetProperty; } else if (membType == MemberTypes.Field) { bindFlags = BindingFlags.SetField; } else { return(false); } if (!ReflectionUtil.InvokeMember( secAttrType, name, bindFlags, null, activatedObj, narg, out excp)) { return(false); } } } SecurityAttribute secAttr = activatedObj as SecurityAttribute; if (secAttr == null) { return(false); } IPermission secPerm = secAttr.CreatePermission(); if (secAttr != null) { PermissionSet permSet = null; if (!permissionSets.TryGetValue(secAction, out permSet)) { permSet = new PermissionSet(null); permissionSets.Add(secAction, permSet); } else if (permSet == null) { permSet = new PermissionSet(null); permissionSets[secAction] = permSet; } DebugUtil.Assert(permSet != null); permSet.AddPermission(secPerm); return(true); } return(false); }
//------------------------------------------------------------ // FUNCBREC.BindNubSave // /// <summary> /// Fill in the given slot (iexpr) of the NubInfo appropriately. /// If exprSrc is a constant (possibly with side effects), /// put the side effects in nin.rgexprPre[iexpr] and the constant value in nin.rgexprVal[iexpr]. /// Otherwise, construct an expr to save the value of exprSrc in a temp, /// an expr to load the temp and an expr to free the temp. /// Store these in the appropriate places in the NubInfo. /// If fLift is true, the value saved in the temp will have at most one level of Nullable. /// </summary> /// <param name="srcExpr"></param> /// <param name="nubInfo"></param> /// <param name="exprIndex"></param> /// <param name="fLift"></param> /// <returns></returns> //------------------------------------------------------------ private bool BindNubSave(EXPR srcExpr, ref NubInfo nubInfo, int exprIndex, bool fLift) { DebugUtil.Assert(exprIndex == 0 || exprIndex == 1); DebugUtil.Assert( nubInfo.PreExpr[exprIndex] == null && nubInfo.PostExpr[exprIndex] == null && nubInfo.ValueExpr[exprIndex] == null && nubInfo.TmpExpr[exprIndex] == null && nubInfo.ConditionExpr[exprIndex] == null); // If we're lifting the expr and it's a new T?(t), just operate on t. The caller should have // already taken care of calling StripNubCtor! DebugUtil.Assert(!srcExpr.TypeSym.IsNUBSYM || !fLift || !IsNubCtor(srcExpr)); // Check for an EXPRKIND.CONSTANT or EXPRKIND.ZEROINIT inside EXPRKIND.SEQUENCE and EXPRKIND.SEQREV exprs. EXPR constExpr = srcExpr.GetConst(); if (constExpr != null) { DebugUtil.Assert(constExpr.Kind == EXPRKIND.CONSTANT || constExpr.Kind == EXPRKIND.ZEROINIT); if (constExpr != srcExpr) { // Keep the side effects. nubInfo.PreExpr[exprIndex] = srcExpr; } if (!constExpr.TypeSym.IsNUBSYM || !fLift) { nubInfo.TmpExpr[exprIndex] = constExpr; } else { nubInfo.TmpExpr[exprIndex] = NewExprZero( srcExpr.TreeNode, constExpr.TypeSym.StripAllButOneNub()); } return(false); } if (srcExpr.TypeSym.IsNUBSYM && fLift) { while (srcExpr.TypeSym.ParentSym.IsNUBSYM) { srcExpr = BindNubGetValOrDef(srcExpr.TreeNode, srcExpr); } } if (srcExpr.Kind == EXPRKIND.LDTMP) { // The thing is already in a temp, no need to put it in another. nubInfo.PreExpr[exprIndex] = srcExpr; nubInfo.TmpExpr[exprIndex] = srcExpr; return(true); } // Create the temp. EXPRSTTMP tmpStExpr = NewExpr(srcExpr.TreeNode, EXPRKIND.STTMP, srcExpr.TypeSym) as EXPRSTTMP; EXPRLDTMP tmpLdExpr = NewExpr(srcExpr.TreeNode, EXPRKIND.LDTMP, srcExpr.TypeSym) as EXPRLDTMP; EXPRFREETMP tmpFreeExpr = NewExpr(srcExpr.TreeNode, EXPRKIND.FREETMP, srcExpr.TypeSym) as EXPRFREETMP; tmpStExpr.SourceExpr = srcExpr; tmpStExpr.Flags |= EXPRFLAG.ASSGOP; tmpLdExpr.TmpExpr = tmpStExpr; tmpFreeExpr.TmpExpr = tmpStExpr; tmpFreeExpr.Flags |= EXPRFLAG.ASSGOP; nubInfo.PreExpr[exprIndex] = tmpStExpr; nubInfo.PostExpr[exprIndex] = tmpFreeExpr; nubInfo.TmpExpr[exprIndex] = tmpLdExpr; return(true); }
// The following methods comprise the error handling/COMPILER-to-CController hosting //------------------------------------------------------------ // CController.CreateError (1) // /// <summary> /// <para>This function creates a CError object from the given information. /// The CError object is created with no location information. /// The CError object is returned with a ref count of 0.</para> /// </summary> /// <param name="errorId">Error ID.</param> /// <param name="args">Arguments for error message.</param> /// <param name="error">A created CError instance will be set.</param> /// <param name="warnOverride">if true, treats a error as a warning.</param> /// <returns>if failed to create a instance, return false.</returns> /// <remarks> /// <para>If "warnOverride" is true (defaults to false), and this error is usually /// an error (not warning or fatal), then the error is wrapped with warning WRN_ErrorOverride</para> /// </remarks> //------------------------------------------------------------ internal bool CreateError( CSCERRID errorId, ErrArg[] args, out CError error, bool warnOverride) // = false); { error = null; // Make some assertions... DebugUtil.Assert(errorId > 0 && errorId < CSCERRID.ERR_COUNT); DebugUtil.Assert(errorId != CSCERRID.WRN_ErrorOverride); CError errorObject = null; int errNo; int level1, level2; // when errorId is invalid, or has no level, return false; if (!CSCErrorInfo.Manager.GetInfo(errorId, out errNo, out level1)) { goto LERROR; } if (level1 == 0 && warnOverride) { // If errorId is of ERROR and should treat it as WARNING, // and if CSCERRID.WRN_ErrorOverride is lower than optionData.WarnLevel, // return false. if (CSCErrorInfo.Manager.GetWarningLevel(CSCERRID.WRN_ErrorOverride, out level2)) { if (!CheckDisplayWarning(CSCERRID.WRN_ErrorOverride, level2)) { return(true); } } } else { // Clear this bit (since we clearly aren't overriding an error to a warning) warnOverride = false; // If it's a warning, does it meet the warning level criteria? if (level1 > 0 && !CheckDisplayWarning(errorId, level1)) { return(true); } } // Create a CError instance and initialize it. errorObject = new CError(); if (errorObject == null || !errorObject.Initialize((CSCERRID)errorId, args)) { goto LERROR; } // Do we need to wrap this Error in a warning? if (warnOverride == true) { DebugUtil.Assert(errorObject.Kind == ERRORKIND.ERROR); if (!errorObject.Initialize( CSCERRID.WRN_ErrorOverride, new ErrArg(errorObject.Text), new ErrArg(errorObject.ErrorID))) { goto LERROR; } } // Now check to see if we need to promote this warning to an error if (errorObject.Kind == ERRORKIND.WARNING && this.OptionManager.IsWarnAsError(errorObject.ErrorID) && !errorObject.WarnAsError()) { goto LERROR; } error = errorObject; return(true); LERROR: if (errorObject != null && !String.IsNullOrEmpty(errorObject.Text)) { OnCatastrophicError(errorObject.Text); } else { OnCatastrophicError("CController.CreateError"); } error = null; return(false); }
//------------------------------------------------------------ // 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.BindBinaryOperator // // EXPR * BindIntBinOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg1, EXPR * arg2); // EXPR * BindRealBinOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg1, EXPR * arg2); // EXPR * BindDecBinOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg1, EXPR * arg2); // EXPR * BindStrBinOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg1, EXPR * arg2); // EXPR * BindShiftOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg1, EXPR * arg2); // EXPR * BindBoolBinOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg1, EXPR * arg2); // EXPR * BindBoolBitwiseOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg1, EXPR * arg2); // EXPR * BindDelBinOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg1, EXPR * arg2); // EXPR * BindEnumBinOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg1, EXPR * arg2); // // EXPR * BindStrCmpOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg1, EXPR * arg2); // EXPR * BindRefCmpOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg1, EXPR * arg2); // EXPR * BindPtrBinOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg1, EXPR * arg2); // EXPR * BindPtrCmpOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg1, EXPR * arg2); // /// <summary></summary> /// <param name="op"></param> /// <param name="tree"></param> /// <param name="ek"></param> /// <param name="flags"></param> /// <param name="arg1"></param> /// <param name="arg2"></param> /// <returns></returns> //------------------------------------------------------------ private EXPR BindBinaryOperator( BindBinOpEnum op, BASENODE tree, EXPRKIND ek, EXPRFLAG flags, EXPR arg1, EXPR arg2) { switch (op) { case BindBinOpEnum.Integer: // Handles standard binary integer based operators. // EXPR * FUNCBREC::BindIntBinOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg1, EXPR * arg2) DebugUtil.Assert( arg1.TypeSym.IsPredefined() && arg2.TypeSym.IsPredefined() && arg1.TypeSym.GetPredefType() == arg2.TypeSym.GetPredefType()); return(BindIntOp(tree, ek, flags, arg1, arg2, arg1.TypeSym.GetPredefType())); case BindBinOpEnum.Real: // Handles standard binary floating point (float, double) based operators. // EXPR * FUNCBREC::BindRealBinOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg1, EXPR * arg2) DebugUtil.Assert( arg1.TypeSym.IsPredefined() && arg2.TypeSym.IsPredefined() && arg1.TypeSym.GetPredefType() == arg2.TypeSym.GetPredefType()); return(BindFloatOp(tree, ek, flags, arg1, arg2)); case BindBinOpEnum.Decimal: return(BindDecBinOp(tree, ek, flags, arg1, arg2)); case BindBinOpEnum.String: // Handles string concatenation. // EXPR * BindStrBinOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg1, EXPR * arg2); DebugUtil.Assert(ek == EXPRKIND.ADD); DebugUtil.Assert( arg1.TypeSym.IsPredefType(PREDEFTYPE.STRING) || arg2.TypeSym.IsPredefType(PREDEFTYPE.STRING)); return(BindStringConcat(tree, arg1, arg2)); case BindBinOpEnum.Shift: return(BindShiftOp(tree, ek, flags, arg1, arg2)); case BindBinOpEnum.Bool: return(BindBoolBinOp(tree, ek, flags, arg1, arg2)); case BindBinOpEnum.BoolBitwise: return(BindBoolBitwiseOp(tree, ek, flags, arg1, arg2)); case BindBinOpEnum.Delegate: return(BindDelegateBinOp(tree, ek, flags, arg1, arg2)); case BindBinOpEnum.Enum: return(BindEnumBinOp(tree, ek, flags, arg1, arg2)); case BindBinOpEnum.StringCompare: return(BindStrCmpOp(tree, ek, flags, arg1, arg2)); case BindBinOpEnum.ReferenceCompare: return(BindRefCmpOp(tree, ek, flags, arg1, arg2)); case BindBinOpEnum.Pointer: return(BindPtrBinOp(tree, ek, flags, arg1, arg2)); case BindBinOpEnum.PointerCompare: return(BindPtrCmpOp(tree, ek, flags, arg1, arg2)); default: DebugUtil.Assert(false, "FUNCBREC.BindBinaryOperator"); break; } return(null); }