public ItemUse(Text.Span p, VarLikeConstructUse /*!*/ array, Expression index, bool functionArrayDereferencing = false) : base(p) { Debug.Assert(array != null); this.array = array; this.index = index; this.functionArrayDereferencing = functionArrayDereferencing; }
public ItemUse(Position p, VarLikeConstructUse/*!*/ array, Expression index, bool functionArrayDereferencing = false) : base(p) { Debug.Assert(array != null); this.array = array; this.index = index; this.functionArrayDereferencing = functionArrayDereferencing; }
virtual public void VisitVarLikeConstructUse(VarLikeConstructUse x) { VisitElement(x.IsMemberOf); }
/// <summary> /// Emits IL instructions that ensure that the specified property of an object is /// of the <see cref="PhpArray"/> type. /// </summary> /// <param name="varObject">Represents the instance whose property should be examined.</param> /// <param name="fieldName">A <see cref="SimpleVarUse"/> that evaluates to the property name.</param> /// <param name="ensureArray">Whether to ensure that static property is an array (or an object).</param> /// <remarks>Nothing is expected on the evaluation stack. If the property is of <see cref="PhpArray"/> type /// it is left on the evaluation stack. Otherwise the control is transfered to the end of chain.</remarks> public PhpTypeCode EmitEnsureProperty(VarLikeConstructUse/*!*/ varObject, SimpleVarUse/*!*/ fieldName, bool ensureArray) { // Template: PhpArray EnsurePropertyIsArray(DObject,field,DTypeDesc) Debug.Assert(varObject != null && fieldName != null); Debug.Assert(fieldName is DirectVarUse || fieldName is IndirectVarUse); LocationTypes location; DProperty property = ResolveProperty(varObject, fieldName, out location); ILEmitter il = codeGenerator.IL; PhpField php_field = property as PhpField; if (php_field != null) // we can emit code that manipulates the property directly { // HACK HACK EmitEnsurePhpFieldDirect(php_field, fieldName, ensureArray); } else { switch (location) { case LocationTypes.GlobalCode: { // call EnsurePropertyIsArray codeGenerator.EmitLoadSelf(); fieldName.EmitName(codeGenerator); codeGenerator.EmitLoadClassContext(); if (ensureArray) { il.Emit(OpCodes.Call, Methods.Operators.EnsurePropertyIsArray); } else { codeGenerator.EmitLoadScriptContext(); il.Emit(OpCodes.Call, Methods.Operators.EnsurePropertyIsObject); } break; } case LocationTypes.MethodDecl: { if (ensureArray) this.Lengthen(); // for hop over -> FunctionCall func = varObject as FunctionCall; if (func == null) { varObject.Emit(codeGenerator); } else { this.LoadAddressOfFunctionReturnValue = true; func.Emit(codeGenerator); RecastValueReturnedByFunctionCall(); } fieldName.EmitName(codeGenerator); codeGenerator.EmitLoadClassContext(); if (ensureArray) { il.Emit(OpCodes.Call, Methods.Operators.EnsurePropertyIsArray); } else { codeGenerator.EmitLoadScriptContext(); il.Emit(OpCodes.Call, Methods.Operators.EnsurePropertyIsObject); } EmitErrorCheck(ensureArray); break; } // if the location was FunctionDecl, appropriate code was already generated by GetDProperty } } return (ensureArray ? PhpTypeCode.PhpArray : PhpTypeCode.DObject); }
/// <summary> /// Gets the <see cref="ObjectFieldLazyEmitInfo"/> object stored in collection. /// </summary> /// <param name="var_object"></param> /// <param name="old_IsArrayItem"></param> /// <param name="old_IsLastMember"></param> /// <returns></returns> /// <remarks> /// This method should only be called from <see cref="ChainBuilder.GetObjectForLazyEmit"/> method. /// </remarks> public ObjectFieldLazyEmitInfo GetItem(VarLikeConstructUse var_object, bool old_IsArrayItem, bool old_IsLastMember) { if (stack.Count != 0) { ObjectFieldLazyEmitInfo info = (ObjectFieldLazyEmitInfo)stack.Pop(); Debug.Assert(info != null); info.ObjectForLazyEmit = var_object; info.Old_IsArrayItem = old_IsArrayItem; info.Old_IsLastMember = old_IsLastMember; } return new ObjectFieldLazyEmitInfo(var_object, old_IsArrayItem, old_IsLastMember); }
public void Reset() { objectForLazyEmit = null; }
public ObjectFieldLazyEmitInfo(VarLikeConstructUse var_object, bool old_IsArrayItem, bool old_IsLastMember) { this.objectForLazyEmit = var_object; this.Old_IsArrayItem = old_IsArrayItem; this.Old_IsLastMember = old_IsLastMember; }
/// <summary> /// Tries to find an instance of <see cref="DProperty"/> that corresponds to an instance property given by /// <paramref name="varObject"/> and <paramref name="fieldName"/>. Currently it is possible only if /// <paramref name="varObject"/> represents <B>$this</B> and <paramref name="fieldName"/> is a compile time /// known instance property, which is surely accessible from current location. /// </summary> /// <param name="varObject">Represents the left side of <B>-></B>.</param> /// <param name="fieldName">Represents the right side of <B>-></B>.</param> /// <param name="location">Current location, valid only if the return value is <B>null</B>. Used by the caller to /// decide what kind of run time access should be emitted.</param> /// <returns>A valid non-<B>null</B> <see cref="PhpField"/> if the field was found, <B>null</B> otherwise.</returns> internal DProperty ResolveProperty(VarLikeConstructUse varObject, SimpleVarUse fieldName, out LocationTypes location) { DirectVarUse direct_var = varObject as DirectVarUse; DirectVarUse direct_field_name; if (direct_var != null && (direct_field_name = fieldName as DirectVarUse) != null && direct_var.IsMemberOf == null && direct_var.VarName.IsThisVariableName) { ILEmitter il = codeGenerator.IL; location = codeGenerator.LocationStack.LocationType; switch (location) { case LocationTypes.GlobalCode: { // load $this from one of Main's arguments and check for null Label this_non_null = il.DefineLabel(); codeGenerator.EmitLoadSelf(); il.Emit(OpCodes.Brtrue_S, this_non_null); codeGenerator.EmitPhpException(Methods.PhpException.ThisUsedOutOfObjectContext); il.Emit(OpCodes.Br, TopChain.ErrorLabel); il.MarkLabel(this_non_null, true); return null; } case LocationTypes.FunctionDecl: { // always throws error codeGenerator.EmitPhpException(Methods.PhpException.ThisUsedOutOfObjectContext); il.Emit(OpCodes.Br, TopChain.ErrorLabel); return null; } case LocationTypes.MethodDecl: { CompilerLocationStack.MethodDeclContext context = codeGenerator.LocationStack.PeekMethodDecl(); if (context.Method.IsStatic) { // always throws error codeGenerator.EmitPhpException(Methods.PhpException.ThisUsedOutOfObjectContext); il.Emit(OpCodes.Br, TopChain.ErrorLabel); location = LocationTypes.FunctionDecl; return null; } else { DProperty property; if (context.Type.GetProperty(direct_field_name.VarName, context.Type, out property) == GetMemberResult.OK && !property.IsStatic) { return property; } } break; } } } location = LocationTypes.MethodDecl; return null; }