/// <summary> /// Emit call to <see cref="DynamicCode.Assert"/> or <see cref="DynamicCode.Eval"/>. /// </summary> internal PhpTypeCode EmitEval(EvalKinds kind, Expression/*!*/code, Text.Span span, QualifiedName? currentNamespace, Dictionary<string, QualifiedName> currentAliases) { Debug.Assert(code != null); // LOAD DynamicCode.<Eval | Assert>(<code>, context, definedVariables, self, includer, source, line, column, evalId, naming) if (kind == EvalKinds.Assert) { // an argument of the assert is boxed: EmitBoxing(code.Emit(this)); } else if (kind == EvalKinds.SyntheticEval) { Debug.Assert(code.HasValue()); Debug.Assert(code.GetValue() is string); // an argument of the eval is converted to a string: il.Emit(OpCodes.Ldstr, (string)code.GetValue()); il.Emit(OpCodes.Ldc_I4_1); } else { // an argument of the eval is converted to a string: EmitConversion(code, PhpTypeCode.String); il.Emit(OpCodes.Ldc_I4_0); } var position = new Text.TextPoint(this.SourceUnit.LineBreaks, span.Start); EmitLoadScriptContext(); EmitLoadRTVariablesTable(); EmitLoadSelf(); EmitLoadClassContext(); EmitEvalInfoPass(position.Line, position.Column); EmitNamingContext(currentNamespace, currentAliases, span.Start); il.Emit(OpCodes.Call, (kind == EvalKinds.Assert) ? Methods.DynamicCode.Assert : Methods.DynamicCode.Eval); return (kind == EvalKinds.Assert) ? PhpTypeCode.Boolean : PhpTypeCode.Object; }
public override PhpTypeCode Emit(AssertEx node, CodeGenerator codeGenerator) { // not emitted in release mode: Debug.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("AssertEx"); ILEmitter il = codeGenerator.IL; PhpTypeCode result; if (_inlinedCode != null) { 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)node.CodeEx).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); var position = new Text.TextPoint(codeGenerator.SourceUnit.LineBreaks, node.Span.Start); il.Emit(OpCodes.Ldstr, _inlinedCode); codeGenerator.EmitLoadScriptContext(); il.Emit(OpCodes.Ldstr, codeGenerator.SourceUnit.SourceFile.RelativePath.ToString()); il.LdcI4(position.Line); il.LdcI4(position.Column); 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(EvalKinds.Assert, node.CodeEx, node.Span, null, null); } // handles return value according to the access type: codeGenerator.EmitReturnValueHandling(node, false, ref result); return(result); }