/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/>
		internal override PhpTypeCode Emit(CodeGenerator/*!*/ codeGenerator)
		{
			PhpTypeCode result;

			// emits inclusion and Main() call:
			result = EmitDynamicInclusion(codeGenerator);

			// return value conversion:
			codeGenerator.EmitReturnValueHandling(this, false, ref result);
			return result;
		}
Example #2
0
		/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/>
		internal override PhpTypeCode Emit(CodeGenerator codeGenerator)
		{
			Debug.Assert(access == AccessType.Read || access == AccessType.ReadRef ||
				access == AccessType.ReadUnknown || access == AccessType.None);
			Statistics.AST.AddNode("FunctionCall.Indirect");

			PhpTypeCode result;
			result = codeGenerator.EmitRoutineOperatorCall(null, isMemberOf, null, null, nameExpr, callSignature, access);
            //EmitReturnValueCopy(codeGenerator.IL, result); // (J) already emitted by EmitRoutineOperatorCall
            
            codeGenerator.EmitReturnValueHandling(this, codeGenerator.ChainBuilder.LoadAddressOfFunctionReturnValue, ref result);

            return result;
		}
Example #3
0
        /// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/>
		internal override PhpTypeCode Emit(CodeGenerator/*!*/ codeGenerator)
		{
			Debug.Assert(access == AccessType.Read || access == AccessType.ReadRef || access == AccessType.ReadUnknown
				|| access == AccessType.None, "Invalid access type in FunctionCall");
			Statistics.AST.AddNode("FunctionCall.Direct");

			PhpTypeCode result;

			if (inlined != InlinedFunction.None)
			{
				result = EmitInlinedFunctionCall(codeGenerator);
			}
			else
			{
                if (alreadyEmittedPlace != null)
                {
                    // continuation of HandleLongChain,
                    // this DirectFcnCall was already emitted
                    // and the result was stored into local variable.
                    codeGenerator.IL.Emit(OpCodes.Ldloc, alreadyEmittedPlace);
                    result = PhpTypeCodeEnum.FromType(alreadyEmittedPlace.LocalType);
                }
                else
				// this node actually represents a method call:
                if (isMemberOf != null)
                {
                    // to avoid StackOverflowException due to long isMemberOf chain,
                    // we will avoid recursion, and divide the chain into smaller pieces.
                    HandleLongChain(codeGenerator);

                    if (routine == null)
                    {
                        //result = codeGenerator.EmitRoutineOperatorCall(null, isMemberOf, qualifiedName.ToString(), null, null, callSignature, access);
                        result = codeGenerator.CallSitesBuilder.EmitMethodCall(
                            codeGenerator,
                            Compiler.CodeGenerator.CallSitesBuilder.AccessToReturnType(access),
                            isMemberOf, null,
                            qualifiedName.ToString(), null,
                            callSignature);
                    }
                    else
                        result = routine.EmitCall(
                            codeGenerator, null, callSignature,
                            new ExpressionPlace(codeGenerator, isMemberOf), false, overloadIndex,
                            null/*TODO when CFG*/, position, access, true);
                }
                else
                {
                    // the node represents a function call:
                    result = routine.EmitCall(
                        codeGenerator, fallbackFunctionName,
                        callSignature, null, false, overloadIndex,
                        null, position, access, false);
                }
			}

            // (J) Emit Copy if necessary:
            // routine == null => Copy emitted by EmitRoutineOperatorCall
            // routine.ReturnValueDeepCopyEmitted => Copy emitted
            // otherwise emit Copy if we are going to read it by value
            if (routine != null && !routine.ReturnValueDeepCopyEmitted)
                EmitReturnValueCopy(codeGenerator.IL, result);
            
            // handles return value:
			codeGenerator.EmitReturnValueHandling(this, codeGenerator.ChainBuilder.LoadAddressOfFunctionReturnValue, ref result);

            return result;
		}
Example #4
0
		/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/>
		internal override PhpTypeCode Emit(CodeGenerator/*!*/ codeGenerator)
		{
			Statistics.AST.AddNode("StaticMethodCall.Indirect");

			PhpTypeCode result = codeGenerator.EmitRoutineOperatorCall(type, null, null, null, methodNameVar, callSignature, access);
            //EmitReturnValueCopy(codeGenerator.IL, result); // (J) already emitted by EmitRoutineOperatorCall

			// handles return value:
			codeGenerator.EmitReturnValueHandling(this, codeGenerator.ChainBuilder.LoadAddressOfFunctionReturnValue, ref result);

			return result;
		}
Example #5
0
		/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/>
		internal override PhpTypeCode Emit(CodeGenerator/*!*/ codeGenerator)
		{
			Statistics.AST.AddNode("StaticMethodCall.Direct");

			IPlace instance = null;

			// PHP allows for static invocations of instance method
			if (!method.IsUnknown && !method.IsStatic)
			{
				// if we are in an instance method and the $this for the callee is assignable from
				// current $this, then invoke the method directly with current $this
				if (codeGenerator.LocationStack.LocationType == LocationTypes.MethodDecl)
				{
					CompilerLocationStack.MethodDeclContext method_context = codeGenerator.LocationStack.PeekMethodDecl();
					if (!method_context.Method.IsStatic && method.DeclaringType.IsAssignableFrom(method_context.Type))
					{
						instance = IndexedPlace.ThisArg;
					}
				}
			}

			// class context is unknown or the class is m-decl or completely unknown at compile-time -> call the operator			
			PhpTypeCode result = method.EmitCall(codeGenerator, null, callSignature, instance, runtimeVisibilityCheck,
				overloadIndex, type, position, access, false/* TODO: __call must be called virtually */);

            if (/*method == null || */!method.ReturnValueDeepCopyEmitted)   // (J) Emit Copy only if method is known (=> known PhpRoutine do not emit Copy on return value)
                EmitReturnValueCopy(codeGenerator.IL, result);  // only if we are going to read the resulting value

			// handles return value:
			codeGenerator.EmitReturnValueHandling(this, codeGenerator.ChainBuilder.LoadAddressOfFunctionReturnValue, ref result);

			return result;
		}
Example #6
0
		internal override PhpTypeCode Emit(CodeGenerator/*!*/ codeGenerator)
		{
			Statistics.AST.AddNode("NewEx");

			PhpTypeCode result;

			if (classNameRef.ResolvedType != null && typeArgsResolved)
			{
				// constructor is resolvable (doesn't mean that known) //

				result = classNameRef.ResolvedType.EmitNew(codeGenerator, null, constructor, callSignature, runtimeVisibilityCheck);
			}
			else
			{
				// constructor is unresolvable (a variable is used in type name => type is unresolvable as well) //

				codeGenerator.EmitNewOperator(null, classNameRef, null, callSignature);
				result = PhpTypeCode.Object;
			}

			codeGenerator.EmitReturnValueHandling(this, false, ref result);
			return result;
		}
Example #7
0
		/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/>
		internal override PhpTypeCode Emit(CodeGenerator/*!*/ codeGenerator)
		{
			// not emitted in release mode:
			Debug.Assert(kind != EvalKinds.LambdaFunction, "Invalid eval kind.");
			Debug.Assert(kind != EvalKinds.Assert || codeGenerator.Context.Config.Compiler.Debug, "Assert should be cut off in release mode.");
			Debug.Assert(access == AccessType.None || access == AccessType.Read || access == AccessType.ReadRef);
			Debug.Assert(inlinedCode != null || codeGenerator.RTVariablesTablePlace != null, "Function should have variables table.");
			Statistics.AST.AddNode("EvalEx");

			ILEmitter il = codeGenerator.IL;
            PhpTypeCode result;

			if (inlinedCode != null)
			{
				Debug.Assert(kind == EvalKinds.Assert, "Only assert can be inlined so far.");
				Label endif_label = il.DefineLabel();
				Label else_label = il.DefineLabel();

				// IF DynamicCode.PreAssert(context) THEN
				codeGenerator.EmitLoadScriptContext();
				il.Emit(OpCodes.Call, Methods.DynamicCode.PreAssert);
				il.Emit(OpCodes.Brfalse, else_label);
				if (true)
				{
					// LOAD <evaluated assertion>;
					codeGenerator.EmitBoxing(((Expression)code).Emit(codeGenerator));

					// CALL DynamicCode.PostAssert(context);
					codeGenerator.EmitLoadScriptContext();
					il.Emit(OpCodes.Call, Methods.DynamicCode.PostAssert);

					// LOAD bool CheckAssertion(STACK, <inlined code>, context, <source path>, line, column);
					il.Emit(OpCodes.Ldstr, inlinedCode);
					codeGenerator.EmitLoadScriptContext();
					il.Emit(OpCodes.Ldstr, codeGenerator.SourceUnit.SourceFile.RelativePath.ToString());
					il.LdcI4(this.position.FirstLine);
					il.LdcI4(this.position.FirstColumn);
					codeGenerator.EmitLoadNamingContext();
					il.Emit(OpCodes.Call, Methods.DynamicCode.CheckAssertion);

					// GOTO END IF;
					il.Emit(OpCodes.Br, endif_label);
				}
				// ELSE
				il.MarkLabel(else_label);
				if (true)
				{
					// LOAD true;
					il.Emit(OpCodes.Ldc_I4_1);
				}
				// END IF;
				il.MarkLabel(endif_label);

                result = PhpTypeCode.Object;
			}
			else
			{
                result = codeGenerator.EmitEval(kind, code, position, currentNamespace, aliases);
			}

			// handles return value according to the access type:
			codeGenerator.EmitReturnValueHandling(this, false, ref result);
			return result;
		}