Example #1
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;
		}
Example #2
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);
                }
            }
		}