コード例 #1
0
            public BuilderModellingContext(CSharpGraphBuilder owner, BuildNode node)
            {
                Contract.Requires(owner != null);
                Contract.Requires(node != null);

                this.owner = owner;
                this.node  = node;
            }
コード例 #2
0
ファイル: BuildGraph.cs プロジェクト: roberthusak/AskTheCode
        public BuildNode AddNode(SyntaxNode syntax)
        {
            var nodeId = this.nodeIdProvider.GenerateNewId();
            var node   = new BuildNode(nodeId, syntax);

            this.Nodes.Add(node);
            Contract.Assert(nodeId.Value == this.Nodes.IndexOf(node));

            return(node);
        }
コード例 #3
0
        private InnerFlowEdge TranslateEdge(
            BuildEdge buildEdge,
            BuildNode buildFrom,
            FlowNode flowFrom,
            FlowNode flowTo)
        {
            BoolHandle condition;

            if (buildEdge.ValueCondition?.Sort == Sort.Bool)
            {
                Contract.Assert(buildFrom.VariableModel != null);
                Contract.Assert(buildFrom.VariableModel is BooleanModel);

                var variable = (BuildVariable)buildFrom.VariableModel.AssignmentLeft.Single();

                if (variable.Origin == VariableOrigin.Temporary &&
                    buildFrom.ValueModel?.AssignmentRight?.Single() is Expression valExpr &&
                    References.IsReferenceComparison(
                        this.TranslateExpression(valExpr),
                        out bool areEqual,
                        out var left,
                        out var right))
                {
                    // Reference comparison stored to a temporary variable
                    // (as such, we suppose it is not used anywhere else)
                    if (buildEdge.ValueCondition == ExpressionFactory.False)
                    {
                        condition = this.builder.AddReferenceComparison(!areEqual, left, right);
                    }
                    else
                    {
                        Contract.Assert(buildEdge.ValueCondition == ExpressionFactory.True);
                        condition = this.builder.AddReferenceComparison(areEqual, left, right);
                    }
                }
                else
                {
                    // General boolean variable
                    condition = (BoolHandle)this.TranslateVariable(variable);
                    if (buildEdge.ValueCondition == ExpressionFactory.False)
                    {
                        condition = !condition;
                    }
                    else
                    {
                        Contract.Assert(buildEdge.ValueCondition == ExpressionFactory.True);
                    }
                }
            }
コード例 #4
0
        // TODO: Substitute the temporary variables only used once in the sequence to reduce the number of assignments
        private void ProcessInnerNodesSequence(
            BuildNode buildNode,
            out BuildNode firstBuildNode,
            out BuildNode lastBuildNode,
            out List <Operation> operations)
        {
            operations = new List <Operation>();
            var curNode = buildNode;

            firstBuildNode = curNode;

            while (true)
            {
                if (curNode.Operation == null)
                {
                    var nodeAssignments = this.TranslateAssignments(curNode.VariableModel, curNode.ValueModel);
                    operations.AddRange(nodeAssignments);
                }
                else if (curNode.Operation is HeapOperation heapOp)
                {
                    var heapOps = this.TranslateHeapOperations(curNode.VariableModel, curNode.ValueModel, heapOp);
                    operations.AddRange(heapOps);
                }
                else
                {
                    Contract.Assert(curNode.Operation.Kind == SpecialOperationKind.Assertion);
                }

                if (curNode.OutgoingEdges.Count != 1)
                {
                    break;
                }

                var nextNode = curNode.OutgoingEdges.Single().To;

                if ((nextNode.Operation is BorderOperation && nextNode.Operation.Kind != SpecialOperationKind.Assertion) ||
                    this.ingoingEdges[nextNode].Count > 1)
                {
                    break;
                }

                Contract.Assert(this.ingoingEdges[nextNode].Single().From == curNode);
                curNode = nextNode;
            }

            lastBuildNode = curNode;
        }
コード例 #5
0
        private void MapAssignmentsToFlowNode(
            BuildNode firstBuildNode,
            BuildNode lastBuildNode,
            FlowNode flowNode)
        {
            int valAssignOffset = 0;
            int refAssignOffset = 0;
            int opOffset        = 0;

            foreach (var processedNode in this.GetBuildNodesSequenceRange(firstBuildNode, lastBuildNode))
            {
                // Note that result of the field write will be the updated reference and a new heap version
                bool isRefModel =
                    processedNode.Operation?.Kind == SpecialOperationKind.FieldWrite ||
                    processedNode.VariableModel?.Factory.ValueKind == ValueModelKind.Reference;

                this.buildToFlowNodesMap[processedNode] = new FlowNodeMappedInfo(
                    flowNode,
                    isRefModel ? refAssignOffset : valAssignOffset,
                    opOffset);

                if (isRefModel)
                {
                    if (processedNode.VariableModel?.AssignmentLeft.Count is int count)
                    {
                        refAssignOffset += count;
                    }
                    else
                    {
                        Contract.Assert(processedNode.Operation.Kind == SpecialOperationKind.FieldWrite);

                        var heapOp = (HeapOperation)processedNode.Operation;
                        refAssignOffset += heapOp.Reference.AssignmentLeft.Count;
                    }
                }
                else
                {
                    valAssignOffset += processedNode.VariableModel?.AssignmentLeft.Count ?? 0;
                }

                opOffset++;
            }
        }
コード例 #6
0
 public BuildEdge(BuildNode to, Expression valueCondition = null)
 {
     this.To             = to;
     this.ValueCondition = valueCondition;
 }
コード例 #7
0
 public BuildEdge WithTo(BuildNode to)
 {
     return(new BuildEdge(to, this.ValueCondition));
 }
コード例 #8
0
        private FlowNode TryTranslateBorderNode(BuildNode buildNode)
        {
            var borderOp = buildNode.Operation as BorderOperation;

            if (borderOp == null || borderOp.Kind == SpecialOperationKind.Assertion)
            {
                return(null);
            }

            if (borderOp.Kind == SpecialOperationKind.MethodCall || borderOp.Kind == SpecialOperationKind.ExceptionThrow)
            {
                MethodLocation           location;
                IEnumerable <Expression> flowArguments;

                if (borderOp.Arguments.Any(arg => arg == null))
                {
                    // We cannot model method calls without properly modelling all their arguments first
                    location      = new MethodLocation(borderOp.Method, isExplorationDisabled: true);
                    flowArguments = Enumerable.Empty <Expression>();
                }
                else
                {
                    // TODO: Enable a configurable and extensible approach instead of this hack
                    // Disable exploring the methods from the tool evaluation
                    bool isExplorationDisabled =
                        borderOp.Method.ContainingType.ToString() == "EvaluationTests.Annotations.Evaluation";

                    location = new MethodLocation(borderOp.Method, isExplorationDisabled);
                    var buildArguments = borderOp.Arguments.SelectMany(typeModel => typeModel.AssignmentRight);
                    flowArguments = buildArguments.Select(expression => this.TranslateExpression(expression));
                }

                if (borderOp.Kind == SpecialOperationKind.MethodCall)
                {
                    var returnAssignments = buildNode.VariableModel?.AssignmentLeft
                                            .Select(buildVar => this.TranslateVariable(buildVar));

                    // We don't allow calling base constructors, so the only way to call it is with the "new" operator
                    // TODO: Propagate the information about constructor call other way when the above is supported
                    var callKind = (borderOp.Method.MethodKind == MethodKind.Constructor)
                        ? CallKind.ObjectCreation
                        : borderOp.Method.IsStatic
                            ? CallKind.Static
                            : CallKind.Instance;

                    bool isObjectCreation = (borderOp.Method.MethodKind == MethodKind.Constructor);

                    return(this.builder.AddCallNode(location, flowArguments, returnAssignments, callKind, buildNode.Flags));
                }
                else
                {
                    Contract.Assert(borderOp.Kind == SpecialOperationKind.ExceptionThrow);

                    return(this.builder.AddThrowExceptionNode(location, flowArguments, buildNode.Flags));
                }
            }
            else
            {
                Contract.Assert(borderOp.Kind == SpecialOperationKind.Return);

                var returnValues = buildNode.ValueModel?.AssignmentRight
                                   .Select(expression => this.TranslateExpression(expression))
                                   .ToImmutableArray();

                if ((returnValues == null || returnValues.Value.Length == 0) &&
                    this.BuildGraph.MethodSyntax.Kind() == SyntaxKind.ConstructorDeclaration)
                {
                    // A constructor returns "this" variable by convention
                    var buildThis = this.BuildGraph.Variables.First(v => v.Origin == VariableOrigin.This);
                    returnValues = ImmutableArray.Create((Expression)this.TranslateVariable(buildThis));
                }

                return(this.builder.AddReturnNode(returnValues, buildNode.Flags));
            }
        }