Пример #1
0
        //------------------------------------------------------------
        // 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);
        }
Пример #2
0
        //------------------------------------------------------------
        // 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);
        }