Beispiel #1
0
        /// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/>
        internal override PhpTypeCode Emit(CodeGenerator /*!*/ codeGenerator)
        {
            Debug.Assert(access == AccessType.None || access == AccessType.Read || access == AccessType.ReadRef ||
                         access == AccessType.ReadUnknown);
            Statistics.AST.AddNode("Assign.Ref");

            //ChainBuilder.RefErrorLabelInfo labelInfo;
            ILEmitter il = codeGenerator.IL;

            // Strict Standards: Only variables should be assigned by reference

            /*if (rvalue is FunctionCall)//TODO: only variables (but also variables given by function call return value!)
             * {
             *  il.LdcI4( (int)PhpError.Strict );
             *  il.Emit(OpCodes.Ldstr, CoreResources.GetString("only_vars_assign ed_by_ref"));
             *  codeGenerator.EmitPhpException(il,Methods.PhpException.Throw);
             * }*/

            // PREPARE:
            codeGenerator.ChainBuilder.Create();
            lvalue.Emit(codeGenerator);

            // LOAD <right hand side>:
            codeGenerator.ChainBuilder.Create();
            rvalue.Emit(codeGenerator);
            codeGenerator.ChainBuilder.End();

            PhpTypeCode result;

            // Dup source value if assignment is read
            switch (access)
            {
            case AccessType.Read:
            case AccessType.ReadUnknown:
            case AccessType.ReadRef:
            {
                // DUP
                il.Emit(OpCodes.Dup);

                // STORE tmp
                il.Stloc(il.GetAssignmentLocalRef());

                // STORE prepared,result
                lvalue.EmitAssign(codeGenerator);

                // LOAD DEREF tmp
                il.Ldloc(il.GetAssignmentLocalRef());

                if (access == AccessType.Read)
                {
                    il.Emit(OpCodes.Ldfld, Fields.PhpReference_Value);
                    result = PhpTypeCode.Object;
                }
                else
                {
                    result = PhpTypeCode.PhpReference;
                }
                break;
            }

            case AccessType.None:
                lvalue.EmitAssign(codeGenerator);
                result = PhpTypeCode.Void;
                break;

            default:
                Debug.Fail();
                result = PhpTypeCode.Invalid;
                break;
            }
            codeGenerator.ChainBuilder.End();

            return(result);
        }