private void Analyze(IStatement statement, ReachabilityGraph graph, VariableScope scope)
        {
            switch (statement)
            {
            default:
                throw ExhaustiveMatch.Failed(statement);

            case IVariableDeclarationStatement stmt:
            {
                var initializer = AnalyzeAssignmentSource(stmt.Initializer, graph, scope);
                var variable    = VariableDeclared(stmt, graph, scope);
                // TODO this variable's references effectively go away when it is no longer live
                // TODO how does the idea of in use variables work with variables?
                graph.Assign(variable, initializer);
                if (!stmt.VariableIsLiveAfter.Result)
                {
                    // Variable is dead, effectively it can be removed
                    variable?.Dead();
                }
            }
            break;

            case IExpressionStatement stmt:
                Analyze(stmt.Expression, graph, scope);
                break;

            case IResultStatement exp:
                // TODO deal with passing the result to the block
                Analyze(exp.Expression, graph, scope);
                break;
            }
        }
Esempio n. 2
0
        public void AddNewObjectWithValueType()
        {
            var graph          = new ReachabilityGraph();
            var mockExpression = new Mock <INewObjectExpression>();

            mockExpression.Setup(e => e.DataType).Returns(DataType.Int);

            var temp = graph.AddObject(mockExpression.Object);

            Assert.Null(temp);
            Assert.Empty(graph.ReferenceGraph.Objects);
            Assert.Empty(graph.ReferenceGraph.TempValues);
        }
Esempio n. 3
0
        public void AddParameterWithValueType()
        {
            var graph              = new ReachabilityGraph();
            var mockParameter      = new Mock <IBindingParameter>();
            var fakeFuncSymbol     = new FunctionSymbol(new PackageSymbol("my.package"), "func", FixedList <DataType> .Empty, DataType.Void);
            var fakeVariableSymbol = new VariableSymbol(fakeFuncSymbol, "var_name", null, false, DataType.Bool);

            mockParameter.Setup(p => p.Symbol).Returns(fakeVariableSymbol);

            var localVariable = graph.AddParameter(mockParameter.Object);

            Assert.Null(localVariable);
            Assert.Empty(graph.ReferenceGraph.CallerVariables);
            Assert.Empty(graph.ReferenceGraph.Variables);
        }
Esempio n. 4
0
        public void AddNewObject()
        {
            var graph          = new ReachabilityGraph();
            var mockExpression = new Mock <INewObjectExpression>();
            // TODO this type should be Isolated or Owned
            var fakeReferenceType = new ObjectType(NamespaceName.Global, "Fake", false, ReferenceCapability.Shared);

            mockExpression.Setup(e => e.DataType).Returns(fakeReferenceType);

            var temp = graph.AddObject(mockExpression.Object);

            Assert.NotNull(temp);
            Assert.Collection(graph.ReferenceGraph.Objects, o =>
            {
                Assert.Equal(mockExpression.Object, o.OriginSyntax);
                Assert.Single(temp !.PossibleReferents, o);
                // TODO what else to test
            });
        private void Analyze()
        {
            var graph = new ReachabilityGraph();
            var scope = CreateParameterScope(graph);

            switch (declaration)
            {
            default:
                throw ExhaustiveMatch.Failed(declaration);

            case IConcreteInvocableDeclaration syn:
                foreach (var statement in syn.Body.Statements)
                {
                    Analyze(statement, graph, scope);
                }
                break;

            case IFieldDeclaration _:
                // TODO support field initializers
                //Analyze(syn.Initializer, graph, scope);
                break;
            }
            // TODO handle implicit return at end
        }
        /// <summary>
        /// Analyze an expression to apply its effects to the reachability graph.
        /// </summary>
        /// <returns>The place of the object resulting from evaluating this expression or null
        /// if the there is no result or the result is not an object reference.</returns>
        private TempValue?Analyze(IExpression?expression, ReachabilityGraph graph, VariableScope scope)
        {
            if (expression is null)
            {
                return(null);
            }
            var referenceType   = expression.DataType.Known().UnderlyingReferenceType();
            var isReferenceType = !(referenceType is null);

            switch (expression)
            {
            default:
                throw ExhaustiveMatch.Failed(expression);

            case IAssignmentExpression exp:
            {
                var leftPlace  = AnalyzeAssignmentPlace(exp.LeftOperand, graph, scope);
                var rightPlace = AnalyzeAssignmentSource(exp.RightOperand, graph, scope);
                graph.Assign(leftPlace, rightPlace);
                return(null);
            }

            case ISelfExpression exp:
                throw new InvalidOperationException($"`self` reference not wrapped in move, borrow, or share");

            case IMoveExpression exp:
            {
                _ = referenceType ?? throw new InvalidOperationException("Can't move value type");

                // The referent should be a name or `self` so we don't need to evaluate it
                var variable = graph.GetVariableFor(exp.ReferencedSymbol);
                var temp     = graph.AddTempValue(exp);
                temp?.MoveFrom(variable);
                return(temp);
            }

            case IBorrowExpression exp:
            {
                _ = referenceType ?? throw new InvalidOperationException("Can't borrow value type");

                // If there is a variable, it is a simple borrow expression
                var variable = graph.TryGetVariableFor(exp.ReferencedSymbol);
                if (!(variable is null))
                {
                    var temp = graph.AddTempValue(exp);
                    temp?.BorrowFrom(variable);
                    return(temp);
                }

                // Can this happen?
                throw new NotImplementedException();
                //var temp = Analyze(exp.)
                //var temp = graph.NewTempValue(referenceType);
                //temp.BorrowFrom(variable);
                //return temp;
            }

            case IShareExpression exp:
            {
                _ = referenceType ?? throw new InvalidOperationException("Can't share value type");

                // The referent should be a name or `self` so we don't need to evaluate it
                var variable = graph.TryGetVariableFor(exp.ReferencedSymbol);
                if (!(variable is null))
                {
                    var temp = graph.AddTempValue(exp);
                    temp?.ShareFrom(variable);
                    return(temp);
                }