예제 #1
0
        /// <summary>
        /// Gets a string which is used as a fill in the code to be parsed in order to maintain
        /// correct token positioning.
        /// </summary>
        /// <param name="args">A position of string literal holding source code for lambda function arguments.</param>
        /// <param name="body">A position of string literal holding source code for the body.</param>
        /// <returns>A string containing spaces and end-of-line characters '\n'.</returns>
        private static string GetInlinedLambdaCodeFill(PHP.Core.Text.TextSpan args, PHP.Core.Text.TextSpan body)
        {
            int delta_lines = body.FirstLine - args.LastLine;

            if (delta_lines == 0)
            {
                // ....args.......'_____,_______________'.......body.....
                // ...............)_________fill________{................
                return(new String(' ', body.FirstColumn - args.LastColumn - 1));
            }
            else
            {
                // source:
                // .....args.....'_____\r\n
                // _________,_____\r\n
                // ____________'......body.....

                // code to parse:
                // .....args....'\n
                // \n
                // ____fill____{.....body......

                // the same number of lines as it is in the source file + leading columns:
                return(new System.Text.StringBuilder(delta_lines + body.FirstColumn).
                       Append('\n', delta_lines).Append(' ', body.FirstColumn).ToString());
            }
        }
예제 #2
0
        public static PHP.Core.Compiler.AST.FunctionCallEvaluateInfo CreateFunction_Analyze(
            Analyzer analyzer,
            PHP.Core.AST.CallSignature callSignature,
            string args, string body)
        {
            if (analyzer.IsInsideIncompleteClass())
            {
                return(null);  // in this case, the DirectFnCall will not be Emitted. Therefore the lambda routine will not be declared and compilation will fail when emitting not fully declared lambda FunctionDecl.
            }
            // has to be a valid identifier:
            // actually this name is never used then
            string function_name = "__" + Guid.NewGuid().ToString().Replace('-', '_'); //DynamicCode.GenerateLambdaName(args, body);

            string prefix1, prefix2;

            DynamicCode.GetLamdaFunctionCodePrefixes(function_name, args, out prefix1, out prefix2);

            var pos_args = new PHP.Core.Text.TextSpan(analyzer.SourceUnit.LineBreaks, callSignature.Parameters[0].Span);
            var pos_body = new PHP.Core.Text.TextSpan(analyzer.SourceUnit.LineBreaks, callSignature.Parameters[1].Span);

            // function __XXXXXX(<args>){<fill><body>}
            string fill = GetInlinedLambdaCodeFill(pos_args, pos_body);
            string code = String.Concat(prefix2, fill, body, "}");

            // parses function source code:

            // the position of the first character of the parsed code:
            // (note that escaped characters distort position a little bit, which cannot be eliminated so easily)
            var counter = new PHP.Core.Parsers.Parser.ReductionsCounter();
            var ast     = analyzer.BuildAst(pos_args.Start.Position - prefix1.Length + 1, code, counter);

            if (ast == null || ast.Statements == null)
            {
                return(null);   // the function cannot be parsed
            }
            Debug.Assert(counter.FunctionCount == 1);

            var decl_node = (PHP.Core.AST.FunctionDecl)ast.Statements[0];

            // adds declaration to the end of the global code statement list:
            analyzer.AddLambdaFcnDeclaration(decl_node);

            //
            return(new PHP.Core.Compiler.AST.FunctionCallEvaluateInfo()
            {
                //.inlined = InlinedFunction.CreateFunction;
                emitDeclareLamdaFunction = true,

                // modify declaration:
                newRoutine = Core.Compiler.AST.FunctionDeclCompilerHelper.ConvertToLambda(decl_node, analyzer),
            });
        }
예제 #3
0
        public static PHP.Core.Compiler.AST.FunctionCallEvaluateInfo CreateFunction_Analyze(
            Analyzer analyzer,
            PHP.Core.AST.CallSignature callSignature,
            string args, string body)
        {
            if (analyzer.IsInsideIncompleteClass())
                return null;  // in this case, the DirectFnCall will not be Emitted. Therefore the lambda routine will not be declared and compilation will fail when emitting not fully declared lambda FunctionDecl.

            // has to be a valid identifier:
            // actually this name is never used then
            string function_name = "__" + Guid.NewGuid().ToString().Replace('-', '_'); //DynamicCode.GenerateLambdaName(args, body);

            string prefix1, prefix2;
            DynamicCode.GetLamdaFunctionCodePrefixes(function_name, args, out prefix1, out prefix2);

            var pos_args = new PHP.Core.Text.TextSpan(analyzer.SourceUnit.LineBreaks, callSignature.Parameters[0].Span);
            var pos_body = new PHP.Core.Text.TextSpan(analyzer.SourceUnit.LineBreaks, callSignature.Parameters[1].Span);

            // function __XXXXXX(<args>){<fill><body>}
            string fill = GetInlinedLambdaCodeFill(pos_args, pos_body);
            string code = String.Concat(prefix2, fill, body, "}");

            // parses function source code:
            
            // the position of the first character of the parsed code:
            // (note that escaped characters distort position a little bit, which cannot be eliminated so easily)
            var counter = new PHP.Core.Parsers.Parser.ReductionsCounter();
            var ast = analyzer.BuildAst(pos_args.Start.Position - prefix1.Length + 1, code, counter);
            if (ast == null || ast.Statements == null)
                return null;   // the function cannot be parsed

            Debug.Assert(counter.FunctionCount == 1);

            var decl_node = (PHP.Core.AST.FunctionDecl)ast.Statements[0];

            // adds declaration to the end of the global code statement list:
            analyzer.AddLambdaFcnDeclaration(decl_node);

            //
            return new PHP.Core.Compiler.AST.FunctionCallEvaluateInfo()
            {
                //.inlined = InlinedFunction.CreateFunction;
                emitDeclareLamdaFunction = true,

                // modify declaration:
                newRoutine = Core.Compiler.AST.FunctionDeclCompilerHelper.ConvertToLambda(decl_node, analyzer),
            };
        }