/// <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; }
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); } } }