public void TestEmpty() { var root = new Program( new Core.Lexer.Range(new StringLocation(0), new StringLocation(1)), new List <StructDeclaration>(), new List <FunctionDeclaration>()); var graph = new Dictionary <FunctionDeclaration, IReadOnlyCollection <VariableDeclaration> >(); var resultExpected = new Dictionary <Node, IReadOnlyCollection <VariableDeclaration> >() { { root, new List <VariableDeclaration>() } }; var callGraphGenerator = new CallGraphGenerator(); var nodeInfoExtractors = new Dictionary <VariableInfo, INodeInfoExtractor> { [VariableInfo.Access] = new AccessInfoExtractor(), [VariableInfo.Modifications] = new ModifyInfoExtractor(), }; var generator = new VariableAccessGraphGenerator(callGraphGenerator, nodeInfoExtractors); var resultActual = generator.GetVariableInfoPerAstNode(root); MappingEquivalence.AssertAreEquivalentCollection(resultExpected, resultActual.Accesses); MappingEquivalence.AssertAreEquivalentCollection(resultExpected, resultActual.Modifies); }
public IVariableAccessGraphGenerator GetGenerator() { var callGraphGenerator = new CallGraphGenerator(); var nodeInfoExtractors = new Dictionary <VariableInfo, INodeInfoExtractor> { [VariableInfo.Access] = new AccessInfoExtractor(), [VariableInfo.Modifications] = new ModifyInfoExtractor(), }; return(new VariableAccessGraphGenerator(callGraphGenerator, nodeInfoExtractors)); }
public void TestCallGraph() { var names = new List <string> { "a", "b", "c" }; var functions = new List <FunctionDeclaration>(); var calls = new List <FunctionCall>(); foreach (var id in names) { var functionCall = new FunctionCall( new Range(new StringLocation(0), new StringLocation(1)), "b", new List <Expression>()); calls.Add(functionCall); var body = new InstructionBlock( new Range(new StringLocation(0), new StringLocation(1)), new List <Expression> { functionCall }); var fun = new FunctionDeclaration( new Range(new StringLocation(0), new StringLocation(1)), id, UnitType.Instance, new List <VariableDeclaration>(), body, false); functions.Add(fun); } foreach (var call in calls) { call.Declaration = functions[1]; } var root = new Program( new Range(new StringLocation(0), new StringLocation(1)), new List <StructDeclaration>(), functions); CallGraphGenerator gen = new CallGraphGenerator(); var dict = gen.BuildCallGraph(root); Assert.AreEqual(1, dict[functions[0]].Count); Assert.AreEqual(1, dict[functions[1]].Count); Assert.AreEqual(1, dict[functions[2]].Count); Assert.IsTrue(dict[functions[0]].Contains(functions[1])); Assert.IsTrue(dict[functions[1]].Contains(functions[1])); Assert.IsTrue(dict[functions[2]].Contains(functions[1])); }
public void TestComplex() { /* Build AST */ var declarationX = AstConstructionUtils.CreateVariableDeclaration("x"); var declarationY = AstConstructionUtils.CreateVariableDeclaration("y"); var assignmentX = AstConstructionUtils.CreateAssignment( declarationX, AstConstructionUtils.CreateVariable(declarationY)); var incrementY = AstConstructionUtils.CreateIncrement(declarationY); var funInner = AstConstructionUtils.CreateFunction( "funInner", new List <Expression> { assignmentX }); var funOuter = AstConstructionUtils.CreateFunction( "funOuter", new List <Expression> { declarationX, declarationY, incrementY, funInner }); var functions = new List <FunctionDeclaration> { funOuter }; var root = new Program( new Core.Lexer.Range(new StringLocation(0), new StringLocation(1)), new List <StructDeclaration>(), functions); /* Prepare graphs */ var accessGraph = new Dictionary <FunctionDeclaration, IReadOnlyCollection <VariableDeclaration> >() { { funInner, new List <VariableDeclaration> { declarationX, declarationY } }, { funOuter, new List <VariableDeclaration> { declarationY } } }; var modificationGraph = new Dictionary <FunctionDeclaration, IReadOnlyCollection <VariableDeclaration> >() { { funInner, new List <VariableDeclaration> { declarationX } }, { funOuter, new List <VariableDeclaration> { declarationY } } }; /* Compute accesses per node */ var accessNothing = new List <Node> { root, funInner, funOuter, declarationX, declarationY, declarationX.Value, declarationY.Value, incrementY.Value }; var accessX = new List <Node> { assignmentX.Lhs }; var accessY = new List <Node> { funOuter.Body, incrementY, incrementY.Lhs, assignmentX.Value }; var accessBoth = new List <Node> { assignmentX, funInner.Body }; var expectedAccesses = new Dictionary <Node, IReadOnlyCollection <VariableDeclaration> >(); foreach (var node in accessNothing) { expectedAccesses[node] = new List <VariableDeclaration>(); } foreach (var node in accessX) { expectedAccesses[node] = new List <VariableDeclaration> { declarationX }; } foreach (var node in accessY) { expectedAccesses[node] = new List <VariableDeclaration> { declarationY }; } foreach (var node in accessBoth) { expectedAccesses[node] = new List <VariableDeclaration> { declarationX, declarationY }; } /* Compute modifications per node */ var modifyNothing = new List <Node> { root, funInner, funOuter, declarationX, declarationY, assignmentX.Lhs, assignmentX.Value, declarationX.Value, declarationY.Value, incrementY.Value, incrementY.Lhs }; var modifyX = new List <Node> { funInner.Body, assignmentX }; var modifyY = new List <Node> { funOuter.Body, incrementY }; var expectedModifications = new Dictionary <Node, IReadOnlyCollection <VariableDeclaration> >(); foreach (var node in modifyNothing) { expectedModifications[node] = new List <VariableDeclaration>(); } foreach (var node in modifyX) { expectedModifications[node] = new List <VariableDeclaration> { declarationX }; } foreach (var node in modifyY) { expectedModifications[node] = new List <VariableDeclaration> { declarationY }; } /* Get results from generator and compare */ var callGraphGenerator = new CallGraphGenerator(); var nodeInfoExtractors = new Dictionary <VariableInfo, INodeInfoExtractor> { [VariableInfo.Access] = new AccessInfoExtractor(), [VariableInfo.Modifications] = new ModifyInfoExtractor(), }; var generator = new VariableAccessGraphGenerator(callGraphGenerator, nodeInfoExtractors); var resultActual = generator.GetVariableInfoPerAstNode(root); MappingEquivalence.AssertAreEquivalentCollection(expectedAccesses, resultActual.Accesses); MappingEquivalence.AssertAreEquivalentCollection(expectedModifications, resultActual.Modifies); }
public void TestInnerFunction() { var functions = new List <FunctionDeclaration>(); var aCall = new FunctionCall( new Range(new StringLocation(0), new StringLocation(1)), "a", new List <Expression>()); var instructionBlock = new InstructionBlock( new Range(new StringLocation(0), new StringLocation(1)), new List <Expression> { aCall }); var b = new FunctionDeclaration( new Range(new StringLocation(0), new StringLocation(1)), "b", UnitType.Instance, new List <VariableDeclaration>(), instructionBlock, false); functions.Add(b); var cCall = new FunctionCall( new Range(new StringLocation(0), new StringLocation(1)), "c", new List <Expression>()); var block = new InstructionBlock( new Range(new StringLocation(0), new StringLocation(1)), new List <Expression> { cCall }); var c = new FunctionDeclaration( new Range(new StringLocation(0), new StringLocation(1)), "c", UnitType.Instance, new List <VariableDeclaration>(), block, false); var bCall = new FunctionCall( new Range(new StringLocation(0), new StringLocation(1)), "b", new List <Expression>()); var body = new InstructionBlock( new Range(new StringLocation(0), new StringLocation(1)), new List <Expression> { bCall, c }); var a = new FunctionDeclaration( new Range(new StringLocation(0), new StringLocation(1)), "a", UnitType.Instance, new List <VariableDeclaration>(), body, false); functions.Add(a); var root = new Program( new Range(new StringLocation(0), new StringLocation(1)), new List <StructDeclaration>(), new List <FunctionDeclaration> { a, b }); aCall.Declaration = a; bCall.Declaration = b; cCall.Declaration = c; CallGraphGenerator gen = new CallGraphGenerator(); var dict = gen.BuildCallGraph(root); Assert.AreEqual(1, dict[b].Count); Assert.AreEqual(1, dict[a].Count); Assert.AreEqual(1, dict[c].Count); Assert.IsTrue(dict[b].Contains(a)); Assert.IsTrue(dict[c].Contains(c)); Assert.IsTrue(dict[a].Contains(b)); }