Loading src/main/java/tfm/Main.java +4 −2 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ import tfm.graphs.CFGGraph; import tfm.graphs.Graph; import tfm.graphs.PDGGraph; import tfm.nodes.PDGNode; import tfm.scopes.ScopeHolder; import tfm.utils.Logger; import tfm.visitors.CFGVisitor; import tfm.visitors.PDGVisitor; Loading Loading @@ -68,9 +69,10 @@ public class Main { } }; VoidVisitor<PDGNode> voidVisitor = new PDGVisitor(pdgGraph); ScopeHolder<PDGNode> scopeHolder = new ScopeHolder<>(pdgGraph.getRootNode()); PDGVisitor visitor = new PDGVisitor(pdgGraph, scopeHolder); cu.accept(voidVisitor, pdgGraph.getRootNode()); cu.accept(visitor, scopeHolder); return pdgGraph; } Loading src/main/java/tfm/scopes/BranchedScope.java 0 → 100644 +28 −0 Original line number Diff line number Diff line package tfm.scopes; import tfm.nodes.Node; import tfm.variables.actions.VariableDefinition; import java.util.List; import java.util.stream.Collectors; public class BranchedScope<N extends Node> extends ScopeHolder<N> { public BranchedScope(N node) { super(node); } @Override public List<VariableDefinition<N>> getLastDefinitions(String variable) { return getSubscopes().stream() .flatMap(scope -> scope.getLastDefinitions(variable).stream()) .collect(Collectors.toList()); } @Override public List<VariableDefinition<N>> getLastDefinitionsBeforeNode(String variable, N node) { return getSubscopes().stream() .flatMap(scope -> scope.getLastDefinitionsBeforeNode(variable, node).stream()) .collect(Collectors.toList()); } } src/main/java/tfm/scopes/Scope.java 0 → 100644 +42 −0 Original line number Diff line number Diff line package tfm.scopes; import tfm.nodes.Node; import tfm.variables.actions.VariableDeclaration; import tfm.variables.actions.VariableDefinition; import tfm.variables.actions.VariableUse; import java.util.List; import java.util.Set; public abstract class Scope<N extends Node> { protected N root; protected Scope(N root) { this.root = root; } public N getRoot() { return root; } public abstract void addVariableDeclaration(String variable, N context); public abstract void addVariableDefinition(String variable, N context); public abstract void addVariableUse(String variable, N context); public abstract boolean isVariableDeclared(String variable); public abstract boolean isVariableDefined(String variable); public abstract boolean isVariableUsed(String variable); public abstract List<VariableDeclaration<N>> getVariableDeclarations(String variable); public abstract List<VariableDefinition<N>> getVariableDefinitions(String variable); public abstract List<VariableUse<N>> getVariableUses(String variable); public abstract Set<String> getDeclaredVariables(); public abstract Set<String> getDefinedVariables(); public abstract Set<String> getUsedVariables(); public abstract List<VariableDefinition<N>> getLastDefinitions(String variable); public abstract List<VariableDefinition<N>> getLastDefinitionsBeforeNode(String variable, N node); } src/main/java/tfm/scopes/ScopeHolder.java 0 → 100644 +166 −0 Original line number Diff line number Diff line package tfm.scopes; import tfm.nodes.Node; import tfm.variables.actions.VariableDeclaration; import tfm.variables.actions.VariableDefinition; import tfm.variables.actions.VariableUse; import java.util.*; import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; public class ScopeHolder<N extends Node> extends Scope<N> { private Queue<Scope<N>> subscopes; public ScopeHolder(N root) { super(root); subscopes = Collections.asLifoQueue(new ArrayDeque<>()); } private Optional<Scope<N>> getLastScope() { if (subscopes.isEmpty()) return Optional.empty(); return Optional.of(subscopes.peek()); } @Override public void addVariableDeclaration(String variable, N context) { Optional<Scope<N>> optionalScope = getLastScope(); boolean newScope = !optionalScope.isPresent(); Scope<N> scope = optionalScope.orElse(new VariableScope<>(context)); scope.addVariableDeclaration(variable, context); if (newScope) { addSubscope(scope); } } @Override public void addVariableDefinition(String variable, N context) { Optional<Scope<N>> optionalScope = getLastScope(); boolean newScope = !optionalScope.isPresent(); Scope<N> scope = optionalScope.orElse(new VariableScope<>(context)); scope.addVariableDefinition(variable, context); if (newScope) { addSubscope(scope); } } @Override public void addVariableUse(String variable, N context) { Optional<Scope<N>> optionalScope = getLastScope(); boolean newScope = !optionalScope.isPresent(); Scope<N> scope = optionalScope.orElse(new VariableScope<>(context)); scope.addVariableUse(variable, context); if (newScope) { addSubscope(scope); } } public Queue<Scope<N>> getSubscopes() { return subscopes; } public void addSubscope(Scope<N> subscope) { subscopes.add(subscope); } @Override public boolean isVariableDeclared(String variable) { return subscopes.stream().anyMatch(subscope -> subscope.isVariableDeclared(variable)); } @Override public boolean isVariableDefined(String variable) { return subscopes.stream().anyMatch(subscope -> subscope.isVariableDefined(variable)); } @Override public boolean isVariableUsed(String variable) { return subscopes.stream().anyMatch(subscope -> subscope.isVariableUsed(variable)); } @Override public List<VariableDeclaration<N>> getVariableDeclarations(String variable) { return subscopes.stream() .flatMap(scope -> scope.getVariableDeclarations(variable).stream()) .collect(Collectors.toList()); } @Override public List<VariableDefinition<N>> getVariableDefinitions(String variable) { return subscopes.stream() .flatMap(scope -> scope.getVariableDefinitions(variable).stream()) .collect(Collectors.toList()); } @Override public List<VariableUse<N>> getVariableUses(String variable) { return subscopes.stream() .flatMap(scope -> scope.getVariableUses(variable).stream()) .collect(Collectors.toList()); } @Override public Set<String> getDeclaredVariables() { return subscopes.stream() .flatMap(scope -> scope.getDeclaredVariables().stream()) .collect(Collectors.toSet()); } @Override public Set<String> getDefinedVariables() { return subscopes.stream() .flatMap(scope -> scope.getDefinedVariables().stream()) .collect(Collectors.toSet()); } @Override public Set<String> getUsedVariables() { return subscopes.stream() .flatMap(scope -> scope.getUsedVariables().stream()) .collect(Collectors.toSet()); } @Override public List<VariableDefinition<N>> getLastDefinitions(String variable) { Optional<Scope<N>> scope = subscopes.stream() .filter(_scope -> _scope.isVariableDefined(variable)) .findFirst(); if (!scope.isPresent()) return new ArrayList<>(0); return scope.get().getLastDefinitions(variable); } @Override public List<VariableDefinition<N>> getLastDefinitionsBeforeNode(String variable, N node) { Optional<Scope<N>> scope = subscopes.stream() .filter(_scope -> _scope.isVariableDefined(variable) && _scope.root.getId() <= node.getId()) .findFirst(); if (!scope.isPresent()) return new ArrayList<>(0); return scope.get().getLastDefinitions(variable); } } src/main/java/tfm/scopes/VariableScope.java 0 → 100644 +134 −0 Original line number Diff line number Diff line package tfm.scopes; import tfm.nodes.Node; import tfm.variables.actions.VariableAction; import tfm.variables.actions.VariableDeclaration; import tfm.variables.actions.VariableDefinition; import tfm.variables.actions.VariableUse; import java.util.*; import java.util.stream.Collectors; public class VariableScope<N extends Node> extends Scope<N> { private Map<String, List<VariableDeclaration<N>>> variableDeclarations; private Map<String, List<VariableDefinition<N>>> variableDefinitions; private Map<String, List<VariableUse<N>>> variableUses; public VariableScope(N root) { super(root); variableDeclarations = new HashMap<>(); variableDefinitions = new HashMap<>(); variableUses = new HashMap<>(); } @Override public boolean isVariableDeclared(String variable) { return variableDeclarations.containsKey(variable); } @Override public boolean isVariableDefined(String variable) { return variableDefinitions.containsKey(variable); } @Override public boolean isVariableUsed(String variable) { return variableUses.containsKey(variable); } @Override public List<VariableDeclaration<N>> getVariableDeclarations(String variable) { return new ArrayList<>(variableDeclarations.getOrDefault(variable, new ArrayList<>())); } @Override public List<VariableDefinition<N>> getVariableDefinitions(String variable) { return new ArrayList<>(variableDefinitions.getOrDefault(variable, new ArrayList<>())); } @Override public List<VariableUse<N>> getVariableUses(String variable) { return new ArrayList<>(variableUses.getOrDefault(variable, new ArrayList<>())); } @Override public Set<String> getDeclaredVariables() { return new HashSet<>(variableDeclarations.keySet()); } @Override public Set<String> getDefinedVariables() { return new HashSet<>(variableDefinitions.keySet()); } @Override public Set<String> getUsedVariables() { return new HashSet<>(variableUses.keySet()); } @Override public List<VariableDefinition<N>> getLastDefinitions(String variable) { List<VariableDefinition<N>> res = getVariableDefinitions(variable); if (res.isEmpty()) return res; return res.subList(res.size() - 1, res.size()); } @Override public List<VariableDefinition<N>> getLastDefinitionsBeforeNode(String variable, N node) { List<VariableDefinition<N>> res = getVariableDefinitions(variable); if (res.isEmpty()) return res; Optional<VariableDefinition<N>> target = res.stream() .filter(variableDefinition -> variableDefinition.getNode().getId() <= node.getId()) .max(Comparator.comparingInt(variableDefinition -> variableDefinition.getNode().getId())); return target.map(variableDefinition -> new ArrayList<>(Collections.singletonList(variableDefinition))) .orElseGet(ArrayList::new); } @Override public void addVariableDeclaration(String variable, N context) { appendValue(variableDeclarations, variable, new VariableDeclaration<>(variable, context)); } @Override public void addVariableDefinition(String variable, N context) { appendValue(variableDefinitions, variable, new VariableDefinition<>(variable, context)); } @Override public void addVariableUse(String variable, N context) { appendValue(variableUses, variable, new VariableUse<>(variable, context)); } private <E extends VariableAction<N>> void appendValue(Map<String, List<E>> map, String variable, E action) { List<E> value = map.getOrDefault(variable, new ArrayList<>()); boolean exists = !value.isEmpty(); value.add(action); if (!exists) { map.put(variable, value); } } private <E extends VariableAction<N>> void appendValues(Map<String, List<E>> map, String variable, List<E> actions) { List<E> value = map.getOrDefault(variable, new ArrayList<>()); boolean exists = !value.isEmpty(); value.addAll(actions); if (!exists) { map.put(variable, value); } } } Loading
src/main/java/tfm/Main.java +4 −2 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ import tfm.graphs.CFGGraph; import tfm.graphs.Graph; import tfm.graphs.PDGGraph; import tfm.nodes.PDGNode; import tfm.scopes.ScopeHolder; import tfm.utils.Logger; import tfm.visitors.CFGVisitor; import tfm.visitors.PDGVisitor; Loading Loading @@ -68,9 +69,10 @@ public class Main { } }; VoidVisitor<PDGNode> voidVisitor = new PDGVisitor(pdgGraph); ScopeHolder<PDGNode> scopeHolder = new ScopeHolder<>(pdgGraph.getRootNode()); PDGVisitor visitor = new PDGVisitor(pdgGraph, scopeHolder); cu.accept(voidVisitor, pdgGraph.getRootNode()); cu.accept(visitor, scopeHolder); return pdgGraph; } Loading
src/main/java/tfm/scopes/BranchedScope.java 0 → 100644 +28 −0 Original line number Diff line number Diff line package tfm.scopes; import tfm.nodes.Node; import tfm.variables.actions.VariableDefinition; import java.util.List; import java.util.stream.Collectors; public class BranchedScope<N extends Node> extends ScopeHolder<N> { public BranchedScope(N node) { super(node); } @Override public List<VariableDefinition<N>> getLastDefinitions(String variable) { return getSubscopes().stream() .flatMap(scope -> scope.getLastDefinitions(variable).stream()) .collect(Collectors.toList()); } @Override public List<VariableDefinition<N>> getLastDefinitionsBeforeNode(String variable, N node) { return getSubscopes().stream() .flatMap(scope -> scope.getLastDefinitionsBeforeNode(variable, node).stream()) .collect(Collectors.toList()); } }
src/main/java/tfm/scopes/Scope.java 0 → 100644 +42 −0 Original line number Diff line number Diff line package tfm.scopes; import tfm.nodes.Node; import tfm.variables.actions.VariableDeclaration; import tfm.variables.actions.VariableDefinition; import tfm.variables.actions.VariableUse; import java.util.List; import java.util.Set; public abstract class Scope<N extends Node> { protected N root; protected Scope(N root) { this.root = root; } public N getRoot() { return root; } public abstract void addVariableDeclaration(String variable, N context); public abstract void addVariableDefinition(String variable, N context); public abstract void addVariableUse(String variable, N context); public abstract boolean isVariableDeclared(String variable); public abstract boolean isVariableDefined(String variable); public abstract boolean isVariableUsed(String variable); public abstract List<VariableDeclaration<N>> getVariableDeclarations(String variable); public abstract List<VariableDefinition<N>> getVariableDefinitions(String variable); public abstract List<VariableUse<N>> getVariableUses(String variable); public abstract Set<String> getDeclaredVariables(); public abstract Set<String> getDefinedVariables(); public abstract Set<String> getUsedVariables(); public abstract List<VariableDefinition<N>> getLastDefinitions(String variable); public abstract List<VariableDefinition<N>> getLastDefinitionsBeforeNode(String variable, N node); }
src/main/java/tfm/scopes/ScopeHolder.java 0 → 100644 +166 −0 Original line number Diff line number Diff line package tfm.scopes; import tfm.nodes.Node; import tfm.variables.actions.VariableDeclaration; import tfm.variables.actions.VariableDefinition; import tfm.variables.actions.VariableUse; import java.util.*; import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; public class ScopeHolder<N extends Node> extends Scope<N> { private Queue<Scope<N>> subscopes; public ScopeHolder(N root) { super(root); subscopes = Collections.asLifoQueue(new ArrayDeque<>()); } private Optional<Scope<N>> getLastScope() { if (subscopes.isEmpty()) return Optional.empty(); return Optional.of(subscopes.peek()); } @Override public void addVariableDeclaration(String variable, N context) { Optional<Scope<N>> optionalScope = getLastScope(); boolean newScope = !optionalScope.isPresent(); Scope<N> scope = optionalScope.orElse(new VariableScope<>(context)); scope.addVariableDeclaration(variable, context); if (newScope) { addSubscope(scope); } } @Override public void addVariableDefinition(String variable, N context) { Optional<Scope<N>> optionalScope = getLastScope(); boolean newScope = !optionalScope.isPresent(); Scope<N> scope = optionalScope.orElse(new VariableScope<>(context)); scope.addVariableDefinition(variable, context); if (newScope) { addSubscope(scope); } } @Override public void addVariableUse(String variable, N context) { Optional<Scope<N>> optionalScope = getLastScope(); boolean newScope = !optionalScope.isPresent(); Scope<N> scope = optionalScope.orElse(new VariableScope<>(context)); scope.addVariableUse(variable, context); if (newScope) { addSubscope(scope); } } public Queue<Scope<N>> getSubscopes() { return subscopes; } public void addSubscope(Scope<N> subscope) { subscopes.add(subscope); } @Override public boolean isVariableDeclared(String variable) { return subscopes.stream().anyMatch(subscope -> subscope.isVariableDeclared(variable)); } @Override public boolean isVariableDefined(String variable) { return subscopes.stream().anyMatch(subscope -> subscope.isVariableDefined(variable)); } @Override public boolean isVariableUsed(String variable) { return subscopes.stream().anyMatch(subscope -> subscope.isVariableUsed(variable)); } @Override public List<VariableDeclaration<N>> getVariableDeclarations(String variable) { return subscopes.stream() .flatMap(scope -> scope.getVariableDeclarations(variable).stream()) .collect(Collectors.toList()); } @Override public List<VariableDefinition<N>> getVariableDefinitions(String variable) { return subscopes.stream() .flatMap(scope -> scope.getVariableDefinitions(variable).stream()) .collect(Collectors.toList()); } @Override public List<VariableUse<N>> getVariableUses(String variable) { return subscopes.stream() .flatMap(scope -> scope.getVariableUses(variable).stream()) .collect(Collectors.toList()); } @Override public Set<String> getDeclaredVariables() { return subscopes.stream() .flatMap(scope -> scope.getDeclaredVariables().stream()) .collect(Collectors.toSet()); } @Override public Set<String> getDefinedVariables() { return subscopes.stream() .flatMap(scope -> scope.getDefinedVariables().stream()) .collect(Collectors.toSet()); } @Override public Set<String> getUsedVariables() { return subscopes.stream() .flatMap(scope -> scope.getUsedVariables().stream()) .collect(Collectors.toSet()); } @Override public List<VariableDefinition<N>> getLastDefinitions(String variable) { Optional<Scope<N>> scope = subscopes.stream() .filter(_scope -> _scope.isVariableDefined(variable)) .findFirst(); if (!scope.isPresent()) return new ArrayList<>(0); return scope.get().getLastDefinitions(variable); } @Override public List<VariableDefinition<N>> getLastDefinitionsBeforeNode(String variable, N node) { Optional<Scope<N>> scope = subscopes.stream() .filter(_scope -> _scope.isVariableDefined(variable) && _scope.root.getId() <= node.getId()) .findFirst(); if (!scope.isPresent()) return new ArrayList<>(0); return scope.get().getLastDefinitions(variable); } }
src/main/java/tfm/scopes/VariableScope.java 0 → 100644 +134 −0 Original line number Diff line number Diff line package tfm.scopes; import tfm.nodes.Node; import tfm.variables.actions.VariableAction; import tfm.variables.actions.VariableDeclaration; import tfm.variables.actions.VariableDefinition; import tfm.variables.actions.VariableUse; import java.util.*; import java.util.stream.Collectors; public class VariableScope<N extends Node> extends Scope<N> { private Map<String, List<VariableDeclaration<N>>> variableDeclarations; private Map<String, List<VariableDefinition<N>>> variableDefinitions; private Map<String, List<VariableUse<N>>> variableUses; public VariableScope(N root) { super(root); variableDeclarations = new HashMap<>(); variableDefinitions = new HashMap<>(); variableUses = new HashMap<>(); } @Override public boolean isVariableDeclared(String variable) { return variableDeclarations.containsKey(variable); } @Override public boolean isVariableDefined(String variable) { return variableDefinitions.containsKey(variable); } @Override public boolean isVariableUsed(String variable) { return variableUses.containsKey(variable); } @Override public List<VariableDeclaration<N>> getVariableDeclarations(String variable) { return new ArrayList<>(variableDeclarations.getOrDefault(variable, new ArrayList<>())); } @Override public List<VariableDefinition<N>> getVariableDefinitions(String variable) { return new ArrayList<>(variableDefinitions.getOrDefault(variable, new ArrayList<>())); } @Override public List<VariableUse<N>> getVariableUses(String variable) { return new ArrayList<>(variableUses.getOrDefault(variable, new ArrayList<>())); } @Override public Set<String> getDeclaredVariables() { return new HashSet<>(variableDeclarations.keySet()); } @Override public Set<String> getDefinedVariables() { return new HashSet<>(variableDefinitions.keySet()); } @Override public Set<String> getUsedVariables() { return new HashSet<>(variableUses.keySet()); } @Override public List<VariableDefinition<N>> getLastDefinitions(String variable) { List<VariableDefinition<N>> res = getVariableDefinitions(variable); if (res.isEmpty()) return res; return res.subList(res.size() - 1, res.size()); } @Override public List<VariableDefinition<N>> getLastDefinitionsBeforeNode(String variable, N node) { List<VariableDefinition<N>> res = getVariableDefinitions(variable); if (res.isEmpty()) return res; Optional<VariableDefinition<N>> target = res.stream() .filter(variableDefinition -> variableDefinition.getNode().getId() <= node.getId()) .max(Comparator.comparingInt(variableDefinition -> variableDefinition.getNode().getId())); return target.map(variableDefinition -> new ArrayList<>(Collections.singletonList(variableDefinition))) .orElseGet(ArrayList::new); } @Override public void addVariableDeclaration(String variable, N context) { appendValue(variableDeclarations, variable, new VariableDeclaration<>(variable, context)); } @Override public void addVariableDefinition(String variable, N context) { appendValue(variableDefinitions, variable, new VariableDefinition<>(variable, context)); } @Override public void addVariableUse(String variable, N context) { appendValue(variableUses, variable, new VariableUse<>(variable, context)); } private <E extends VariableAction<N>> void appendValue(Map<String, List<E>> map, String variable, E action) { List<E> value = map.getOrDefault(variable, new ArrayList<>()); boolean exists = !value.isEmpty(); value.add(action); if (!exists) { map.put(variable, value); } } private <E extends VariableAction<N>> void appendValues(Map<String, List<E>> map, String variable, List<E> actions) { List<E> value = map.getOrDefault(variable, new ArrayList<>()); boolean exists = !value.isEmpty(); value.addAll(actions); if (!exists) { map.put(variable, value); } } }