Example #1
0
		/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/>
		internal override void Emit(CodeGenerator/*!*/ codeGenerator)
		{
			Statistics.AST.AddNode("FunctionDecl");

			// marks a sequence point if function is declared here (i.e. is m-decl):
            //Note: this sequence point goes to the function where this function is declared not to this declared function!
			if (!function.IsLambda && function.Declaration.IsConditional)
				codeGenerator.MarkSequencePoint(position.FirstLine, position.FirstColumn, position.LastLine, position.LastColumn + 2);

            // emits attributes on the function itself, its return value, type parameters and regular parameters:
			attributes.Emit(codeGenerator, this);
            signature.Emit(codeGenerator);
			typeSignature.Emit(codeGenerator);

			// prepares code generator for emitting arg-full overload;
			// false is returned when the body should not be emitted:
			if (!codeGenerator.EnterFunctionDeclaration(function)) return;

			// emits the arg-full overload:
			codeGenerator.EmitArgfullOverloadBody(function, body, entireDeclarationPosition, declarationBodyPosition);

			// restores original code generator settings:
			codeGenerator.LeaveFunctionDeclaration();

			// emits function declaration (if needed):
			// ignore s-decl function declarations except for __autoload;
			// __autoload function is declared in order to avoid using callbacks when called:
			if (function.Declaration.IsConditional && !function.QualifiedName.IsAutoloadName)
			{
				Debug.Assert(!function.IsLambda);
				codeGenerator.EmitDeclareFunction(function);
			}
		}
Example #2
0
        /// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/>
        internal override PhpTypeCode Emit(CodeGenerator/*!*/ codeGenerator)
        {
            Statistics.AST.AddNode("LambdaFunctionExpr");
            
            var typeBuilder = codeGenerator.IL.TypeBuilder;

            // define argless and argfull
            this.function.DefineBuilders(typeBuilder);

            //
            codeGenerator.MarkSequencePoint(position.FirstLine, position.FirstColumn, position.LastLine, position.LastColumn + 2);
            if (!codeGenerator.EnterFunctionDeclaration(function))
                throw new Exception("EnterFunctionDeclaration() failed!");

            codeGenerator.EmitArgfullOverloadBody(function, body, entireDeclarationPosition, declarationBodyPosition);
            
            codeGenerator.LeaveFunctionDeclaration();

            // new Closure( <context>, new RoutineDelegate(null,function.ArgLess), <parameters>, <static> )
            codeGenerator.EmitLoadScriptContext();

            var/*!*/il = codeGenerator.IL;
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Ldftn, function.ArgLessInfo);
            il.Emit(OpCodes.Newobj, Constructors.RoutineDelegate);

            int userParamsCount = (useParams != null) ? useParams.Count : 0;
            if (signature.FormalParams != null && signature.FormalParams.Count > userParamsCount)
            {
                // array = new PhpArray(<int_count>, <string_count>);
                il.Emit(OpCodes.Ldc_I4, 0);
                il.Emit(OpCodes.Ldc_I4, signature.FormalParams.Count);
                il.Emit(OpCodes.Newobj, Constructors.PhpArray.Int32_Int32);

                for (int i = userParamsCount; i < signature.FormalParams.Count; i++)
                {
                    var p = signature.FormalParams[i];

                    // CALL array.SetArrayItem("&$name", "<required>" | "<optional>");
                    il.Emit(OpCodes.Dup);   // PhpArray

                    string keyValue = string.Format("{0}${1}", p.PassedByRef ? "&" : null, p.Name.Value);

                    il.Emit(OpCodes.Ldstr, keyValue);
                    il.Emit(OpCodes.Ldstr, (p.InitValue != null) ? "<optional>" : "<required>");
                    il.LdcI4(IntStringKey.StringKeyToArrayIndex(keyValue));

                    il.Emit(OpCodes.Call, Methods.PhpArray.SetArrayItemExact_String);
                }
            }
            else
            {
                il.Emit(OpCodes.Ldnull);
            }

            if (userParamsCount > 0)
            {
                // array = new PhpArray(<int_count>, <string_count>);
                il.Emit(OpCodes.Ldc_I4, 0);
                il.Emit(OpCodes.Ldc_I4, useParams.Count);
                il.Emit(OpCodes.Newobj, Constructors.PhpArray.Int32_Int32);

                foreach (var p in useParams)
                {
                    // <stack>.SetArrayItem{Ref}
                    il.Emit(OpCodes.Dup);   // PhpArray

                    string variableName = p.Name.Value;

                    il.Emit(OpCodes.Ldstr, variableName);
                    if (p.PassedByRef)
                    {
                        DirectVarUse.EmitLoadRef(codeGenerator, p.Name);
                        il.Emit(OpCodes.Call, Methods.PhpArray.SetArrayItemRef_String);
                    }
                    else
                    {
                        // LOAD PhpVariable.Copy( <name>, Assigned )
                        DirectVarUse.EmitLoad(codeGenerator, p.Name);
                        il.LdcI4((int)CopyReason.Assigned);
                        il.Emit(OpCodes.Call, Methods.PhpVariable.Copy);

                        // .SetArrayItemExact( <stack>, <stack>, <hashcode> )
                        il.LdcI4(IntStringKey.StringKeyToArrayIndex(variableName));
                        il.Emit(OpCodes.Call, Methods.PhpArray.SetArrayItemExact_String);
                    }
                }
            }
            else
            {
                il.Emit(OpCodes.Ldnull);
            }

            il.Emit(OpCodes.Newobj, typeof(PHP.Library.SPL.Closure).GetConstructor(new Type[] { typeof(ScriptContext), typeof(RoutineDelegate), typeof(PhpArray), typeof(PhpArray) }));
             
            return PhpTypeCode.Object;
        }