Esempio n. 1
0
        public bool Validate(List <Flag> flags, CancellationToken cancel, bool isCompilerAction = false)
        {
            if (myComprData != null && myComprData.Depth > MaxDepth)
            {
                var flag = new Flag(
                    SeverityKind.Error,
                    AST.Node,
                    Constants.BadSyntax.ToString(
                        string.Format("Comprehension nesting too deep. Maximum nesting depth is {0}.", MaxDepth)),
                    Constants.BadSyntax.Code);
                flags.Add(flag);
                return(RecordValidationResult(false));
            }

            IEnumerable <Node> heads  = null;
            IEnumerable <Body> bodies = null;

            switch (AST.Node.NodeKind)
            {
            case NodeKind.Compr:
                heads  = ((Compr)AST.Node).Heads;
                bodies = ((Compr)AST.Node).Bodies;
                break;

            case NodeKind.Rule:
                heads  = ((Rule)AST.Node).Heads;
                bodies = ((Rule)AST.Node).Bodies;
                break;

            default:
                throw new NotImplementedException();
            }

            if (heads.IsEmpty <Node>())
            {
                var flag = new Flag(
                    SeverityKind.Error,
                    AST.Node,
                    Constants.BadSyntax.ToString("The expression has no heads."),
                    Constants.BadSyntax.Code);
                flags.Add(flag);
                return(RecordValidationResult(false));
            }

            //// Step 1.a. If the body is empty, treat it like a TRUE body.
            var result = true;

            if (bodies.IsEmpty <Body>())
            {
                bodies = EnumerableMethods.GetEnumerable <Body>(MkTrueBody(heads.First <Node>().Span));
            }

            //// Step 1.b. Otherwise, find all the variables (possibly) with selectors
            //// occurring in all the heads. These will be registered with the bodies.
            var varList = new LinkedList <Id>();

            foreach (var h in heads)
            {
                FindVarLikeIds(h, varList);
            }

            //// Step 2. Expand heads / bodies.
            Term            type;
            TypeEnvironment bodyEnv;

            foreach (var b in bodies)
            {
                bodyEnv = TypeEnvironment.AddChild(b);
                var cs = new ConstraintSystem(Index, b, bodyEnv, myComprData);
                if (!cs.Validate(flags, varList, cancel))
                {
                    result = false;
                    continue;
                }

                foreach (var v in cs.Variables)
                {
                    if (cs.TryGetType(v, out type))
                    {
                        bodyEnv.SetType(v, type);
                    }
                }

                foreach (var h in heads)
                {
                    var act = new Action(h, cs, TypeEnvironment, myComprData, AST.Node);
                    if (act.Validate(flags, cancel, isCompilerAction))
                    {
                        actions.AddLast(act);
                    }
                    else
                    {
                        result = false;
                    }

                    if (cancel.IsCancellationRequested)
                    {
                        return(RecordValidationResult(false));
                    }
                }
            }

            if (result && !cancel.IsCancellationRequested)
            {
                TypeEnvironment.JoinTypes();
                Contract.Assert(AST.Node.CompilerData == null);
                AST.Node.CompilerData = TypeEnvironment;
                return(RecordValidationResult(true));
            }
            else
            {
                return(RecordValidationResult(false));
            }
        }