Example #1
0
		internal void EmitDefinition(CodeGenerator/*!*/ codeGenerator)
		{
            if (type.IsComplete)
            {
                Debug.Assert(type.IsComplete, "Incomplete types should be converted to evals.");
                Debug.Assert(type.RealTypeBuilder != null, "A class declared during compilation should have a type builder.");

                attributes.Emit(codeGenerator, this);
                typeSignature.Emit(codeGenerator);

                codeGenerator.EnterTypeDeclaration(type);

                foreach (TypeMemberDecl member_decl in members)
                {
                    member_decl.EnterCodegenerator(codeGenerator);
                    member_decl.Emit(codeGenerator);
                    member_decl.LeaveCodegenerator(codeGenerator);
                }

                // emit stubs for implemented methods & properties that were not declared by this type:
                codeGenerator.EmitGhostStubs(type);

                codeGenerator.LeaveTypeDeclaration();
            }
            else
            {
                Debug.Assert(this.typeDefinitionCode != null);

                // LOAD DynamicCode.Eval(<code>, context, definedVariables, self, includer, source, line, column, evalId)
                
                // wrap Eval into static method
                MethodBuilder method = codeGenerator.IL.TypeBuilder.DefineMethod(
                    string.Format("{0}{1}", ScriptModule.DeclareHelperNane, type.FullName),
                    MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.SpecialName,
                    Types.Void, Types.ScriptContext);

                var il = new ILEmitter(method);
                    
                codeGenerator.EnterLambdaDeclaration(il, false, LiteralPlace.Null, new IndexedPlace(PlaceHolder.Argument, 0), LiteralPlace.Null, LiteralPlace.Null);
                if (true)
                {
                    codeGenerator.EmitEval(
                        EvalKinds.SyntheticEval,
                        new StringLiteral(position, this.typeDefinitionCode, AccessType.Read),
                        position,
                        (this.Namespace != null) ? this.Namespace.QualifiedName : (QualifiedName?)null, this.validAliases);
                    il.Emit(OpCodes.Pop);
                    il.Emit(OpCodes.Ret);
                }
                codeGenerator.LeaveFunctionDeclaration();

                //
                il = codeGenerator.IL;

                type.IncompleteClassDeclareMethodInfo = method;
                type.IncompleteClassDeclarationId = String.Format("{0}${1}:{2}:{3}", type.FullName, unchecked((uint)codeGenerator.SourceUnit.SourceFile.ToString().GetHashCode()), position.FirstLine, position.FirstColumn);

                // sequence point here
                codeGenerator.MarkSequencePoint(position.FirstLine, position.FirstColumn, position.LastLine, position.LastColumn + 2);
                
                if (type.Declaration.IsConditional)
                {
                    // CALL <Declare>.<FullName>(<context>)
                    codeGenerator.EmitLoadScriptContext();
                    il.Emit(OpCodes.Call, method);
                }
                else
                {
                    // if (!<context>.IncompleteTypeDeclared(<id>))
                    //     CALL <Declare>.<FullName>(<context>)
                    var end_if = il.DefineLabel();

                    codeGenerator.EmitLoadScriptContext();
                    il.Emit(OpCodes.Ldstr, type.IncompleteClassDeclarationId);
                    il.Emit(OpCodes.Call, Methods.ScriptContext.IncompleteTypeDeclared);
                    il.Emit(OpCodes.Brtrue, end_if);
                    if (true)
                    {
                        codeGenerator.EmitLoadScriptContext();
                        il.Emit(OpCodes.Call, type.IncompleteClassDeclareMethodInfo);
                    }
                    il.MarkLabel(end_if);
                    il.ForgetLabel(end_if);
                }
            }
		}
Example #2
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 #3
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;
        }