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; } }
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); }
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); }
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); }