예제 #1
0
        internal static LambdaNode ParseAndBindLambda(IHostEnvironment env, string expression, int ivec, DataViewType[] inputTypes, out int[] perm)
        {
            perm = Utils.GetIdentityPermutation(inputTypes.Length);
            if (ivec >= 0)
            {
                if (ivec > 0)
                {
                    perm[0] = ivec;
                    for (int i = 1; i <= ivec; i++)
                    {
                        perm[i] = i - 1;
                    }
                }
            }
            CharCursor chars = new CharCursor(expression);

            var node = LambdaParser.Parse(out List <Error> errors, out List <int> lineMap, chars, perm, inputTypes);

            if (Utils.Size(errors) > 0)
            {
                throw env.ExceptParam(nameof(expression), $"parsing failed: {errors[0].GetMessage()}");
            }

            using (var ch = env.Start("LabmdaBinder.Run"))
                LambdaBinder.Run(env, ref errors, node, msg => ch.Error(msg));

            if (Utils.Size(errors) > 0)
            {
                throw env.ExceptParam(nameof(expression), $"binding failed: {errors[0].GetMessage()}");
            }
            return(node);
        }
        private void Run(string name)
        {
            string outDir = "ExprParser";

            string text         = GetResText(InResName(name));
            string inName       = name + "Input.txt";
            string outName      = name + "Output.txt";
            string outNameAssem = name + "Output.Assem.txt";
            string outPath      = DeleteOutputPath(outDir, outName);
            string outPathAssem = DeleteOutputPath(outDir, outNameAssem);

            using (var wr = OpenWriter(outPath))
            {
                var wrt = new IndentedTextWriter(wr, "  ");

                // Individual scripts are separated by $.
                // Inputs start after #.
                int count   = 0;
                int ichLim  = 0;
                int lineLim = 1;
                for (; ichLim < text.Length; ichLim++)
                {
                    int ichMin  = ichLim;
                    int lineMin = lineLim;

                    while (ichLim < text.Length && text[ichLim] != '$')
                    {
                        if (text[ichLim] == '\n')
                        {
                            lineLim++;
                        }
                        ichLim++;
                    }

                    while (ichMin < ichLim && char.IsWhiteSpace(text[ichMin]))
                    {
                        if (text[ichMin] == '\n')
                        {
                            lineMin++;
                        }
                        ichMin++;
                    }

                    if (ichMin >= ichLim)
                    {
                        continue;
                    }

                    // Process the script.
                    count++;
                    string scriptName = string.Format("Script {0}, lines {1} to {2}", count, lineMin, lineLim);
                    wrt.WriteLine("===== Start {0} =====", scriptName);
                    var types       = ParseTypes(text, ref ichMin, ichLim);
                    int ichLimChars = text.IndexOf('#', ichMin);
                    if (ichLimChars < 0 || ichLimChars >= ichLim)
                    {
                        ichLimChars = ichLim;
                    }
                    else
                    {
                        Contracts.Assert(ichMin < ichLimChars && ichLimChars < ichLim);
                    }
                    CharCursor chars = new CharCursor(text, ichMin, ichLimChars);
                    Delegate   del   = null;
                    lock (_sync)
                    {
                        try
                        {
                            LambdaNode   node;
                            List <Error> errors;
                            List <int>   lineMap;
                            var          perm = Utils.GetIdentityPermutation(types.Length);
                            using (wrt.Nest())
                            {
                                node = LambdaParser.Parse(out errors, out lineMap, chars, perm, types);
                            }
                            Check(node != null, "Null LambdaNode");
                            if (Utils.Size(errors) > 0)
                            {
                                DumpErrors(wrt, lineMap, lineMin, inName, "Parsing", errors);
                                goto LDone;
                            }

                            LambdaBinder.Run(Env, ref errors, node, msg => wr.WriteLine(msg));
                            if (Utils.Size(errors) > 0)
                            {
                                DumpErrors(wrt, lineMap, lineMin, inName, "Binding", errors);
                                goto LDone;
                            }
                            wrt.WriteLine("Binding succeeded. Output type: {0}", node.ResultType);

                            del = LambdaCompiler.Compile(out errors, node);
                            Contracts.Assert(TestFuncs1.Writer == null);
                            TestFuncs1.Writer = wr;
                            if (Utils.Size(errors) > 0)
                            {
                                DumpErrors(wrt, lineMap, lineMin, inName, "Compiling", errors);
                                goto LDone;
                            }

                            wrt.WriteLine("Compiling succeeded.");
                            if (ichLimChars < ichLim)
                            {
                                Evaluate(wrt, del, node.ResultType, types, text, ichLimChars + 1, ichLim);
                            }
                        }
                        catch (Exception ex)
                        {
                            if (!ex.IsMarked())
                            {
                                wrt.WriteLine("Unknown Exception: {0}!", del != null ? del.GetMethodInfo().DeclaringType : (object)"<null>");
                            }
                            wrt.WriteLine("Exception: {0}", ex.Message);
                        }
                        finally
                        {
                            TestFuncs1.Writer = null;
                        }

LDone:
                        wrt.WriteLine("===== End {0} =====", scriptName);
                    }
                }
            }

            CheckEquality(outDir, outName, digitsOfPrecision: 6);

            Done();
        }