/******************************************************************************* * Copyright (c) 2011 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package com.ibm.wala.cast.js.ipa.callgraph.correlations.extraction; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import com.ibm.wala.cast.tree.CAstAnnotation; import com.ibm.wala.cast.tree.CAstControlFlowMap; import com.ibm.wala.cast.tree.CAstEntity; import com.ibm.wala.cast.tree.CAstNode; import com.ibm.wala.cast.tree.CAstNodeTypeMap; import com.ibm.wala.cast.tree.CAstQualifier; import com.ibm.wala.cast.tree.CAstSourcePositionMap; import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position; import com.ibm.wala.cast.tree.CAstType; import com.ibm.wala.cast.tree.rewrite.CAstRewriter.Rewrite; import com.ibm.wala.util.collections.EmptyIterator; import com.ibm.wala.util.collections.HashMapFactory; import com.ibm.wala.util.collections.HashSetFactory; import com.ibm.wala.util.collections.Iterator2Iterable; /** * A simple implementation of {@link CAstEntity} used by the {@link ClosureExtractor}. * * @author mschaefer * */ class ExtractedFunction implements CAstEntity { private final String name; private String[] parms; private final ExtractionPos pos; private Rewrite r; private CAstNode root; private CAstControlFlowMap cfg; private CAstSourcePositionMap posmap; private CAstNodeTypeMap types; private Map> scopedEntities; public ExtractedFunction(String name, ExtractionPos pos) { this.name = name; this.pos = pos; } public void setRewrite(Rewrite r) { assert this.r == null : "Rewrite shouldn't be set more than once."; this.r = r; this.root = r.newRoot(); this.cfg = r.newCfg(); this.posmap = r.newPos(); this.types = r.newTypes(); } @Override public int getKind() { return CAstEntity.FUNCTION_ENTITY; } @Override public String getName() { return name; } @Override public String getSignature() { return null; } @Override public String[] getArgumentNames() { computeParms(); return parms; } @Override public CAstNode[] getArgumentDefaults() { return new CAstNode[0]; } @Override public int getArgumentCount() { computeParms(); return parms.length; } private void computeParms() { if(this.parms == null) { ArrayList parms = new ArrayList<>(); parms.add(name); parms.add("this"); parms.addAll(pos.getParameters()); if(pos.containsThis()) parms.add(pos.getThisParmName()); this.parms = parms.toArray(new String[0]); } } @Override public Map> getAllScopedEntities() { if(scopedEntities == null) { scopedEntities = HashMapFactory.make(); // first, add all existing entities inside the body of this for loop for(Entry> e : r.newChildren().entrySet()) { if(NodePos.inSubtree(e.getKey(), root)) { Collection c = scopedEntities.get(e.getKey()); if(c == null) scopedEntities.put(e.getKey(), c = HashSetFactory.make()); c.addAll(e.getValue()); } } // now, add all new entities which arise from extracted nested for-in loops for(ExtractionPos nested_loop : Iterator2Iterable.make(pos.getNestedLoops())) { CAstNode callsite = nested_loop.getCallSite(); CAstEntity scoped_entity = nested_loop.getExtractedEntity(); Collection c = scopedEntities.get(callsite); if(c == null) scopedEntities.put(callsite, c = HashSetFactory.make()); c.add(scoped_entity); } } return scopedEntities; } @Override public Iterator getScopedEntities(CAstNode construct) { if(getAllScopedEntities().containsKey(construct)) { return getAllScopedEntities().get(construct).iterator(); } else { return EmptyIterator.instance(); } } @Override public CAstNode getAST() { return root; } @Override public CAstControlFlowMap getControlFlow() { return cfg; } @Override public CAstSourcePositionMap getSourceMap() { return posmap; } @Override public Position getPosition() { return getSourceMap().getPosition(root); } @Override public CAstNodeTypeMap getNodeTypeMap() { return types; } @Override public Collection getQualifiers() { return null; } @Override public CAstType getType() { return null; } @Override public Collection getAnnotations() { return null; } @Override public String toString() { return ""; } @Override public Position getPosition(int arg) { return null; } @Override public Position getNamePosition() { return null; } }