Ejemplo n.º 1
0
        /// <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;
        }
Ejemplo n.º 2
0
            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);
            }