private Dictionary <AST.Address, string> getAllFormulas(Depends.DAG graph, bool showProgress) { var frms = graph.getAllFormulaAddrs(); if (showProgress) { Progress p = new Progress("Marshaling", frms.Length); p.Show(); p.Refresh(); var d = frms .Select(addr => { var t = new Tuple <AST.Address, string>(addr, graph.getFormulaAtAddress(addr)); p.increment(); return(t); }).ToDictionary(tup => tup.Item1, tup => tup.Item2); p.Hide(); return(d); } else { return (frms .Select(addr => { return new Tuple <AST.Address, string>(addr, graph.getFormulaAtAddress(addr)); }).ToDictionary(tup => tup.Item1, tup => tup.Item2)); } }
private static FPCoreAST.FPCore convertToFPCore( Group g, Fingerprint fingerprint, Dictionary<Source, ExpressionTools.EData> edatas, Depends.DAG graph, PreList prelist) { // get invocations for this function var f_invocations = g.Functions[fingerprint]; var invocation = f_invocations.First(); var faddr = invocation.First().Tail; // get bindings for this invocation var bindings = new Dictionary<Tuple<AST.Address,bool,bool>, string>(); foreach (var vectref in invocation) { var ref_resultant = ExceLint.Vector.RelativeVector(vectref.Head, vectref.Tail, graph); // not every vector gets a variable (e.g., references to functions) if (g.Variables[fingerprint].ContainsKey(ref_resultant)) { var variable = g.Variables[fingerprint][ref_resultant]; var key = AddrToBindingKey(vectref.Head); if (!bindings.ContainsKey(key)) { bindings.Add(key, variable); } } } return XL2FPCore.FormulaToFPCore(edatas[faddr].Expression, prelist, bindings, g.Provenance[fingerprint].ToArray()); }
private static Group groupFunctions(Depends.DAG graph, Dictionary<AST.Address, string> formulas) { var functions = new Functions(); var variables = new Variables(); var provenance = new Provenance(); // group formulas and invocations by resultant foreach (var f in formulas) { var addr = f.Key; // return all references var refs = ExpressionTools.transitiveRefs(addr, graph); // compute resultant var res = Vector.run(addr, graph); // save each 'function' if (!functions.ContainsKey(res)) { functions.Add(res, new List<ExpressionTools.Vector[]>()); } functions[res].Add(refs); // assign a fresh variable to each unique reference if (!variables.ContainsKey(res)) { // never seen this function before var vm = new VariableMaker(); variables.Add(res, new Dictionary<Countable, string>()); // we only want unique path resultants for data var resultants = refs .Where(r => !graph.isFormula(r.Head)) .Select(r => ExceLint.Vector.RelativeVector(r.Head, r.Tail, graph)) .Distinct(); // assign variable foreach (var r in resultants) { if (!variables[res].ContainsKey(r)) { variables[res].Add(r, vm.nextVariable()); } } } // track provenance if (!provenance.ContainsKey(res)) { var ps = new List<AST.Address>(); provenance.Add(res, ps); } provenance[res].Add(addr); } return new Group(functions, variables, provenance); }
public static string[] extractAll(Depends.DAG graph, Dictionary<AST.Address, string> formulas, List<ProblemReport> pr) { // init MemoDB var mdbo = MemoDBOpt.Some(new MemoDBO()); // group formulas by 'function' var g = groupFunctions(graph, formulas); // allocate return array var fpcores = new List<string>(); // produce a string for each fingerprinted 'function' foreach (var fkvp in g.Functions) { Fingerprint fingerprint = fkvp.Key; // the fingerprint that characterizes the 'function' var invocations = fkvp.Value; // invocations of this function Dictionary<Source, ExpressionTools.EData> edatas = null; try { // inline all formulas and index by invoking cell address edatas = invocations.Select(references => { var faddr = references[0].Tail; return new Tuple<Source, ExpressionTools.EData>(faddr, inlineExpression(faddr, graph, mdbo)); }).ToDictionary(kvp => kvp.Item1, kvp => kvp.Item2); } catch (Exception) { // TODO: fix occasional out-of-bounds error for invocations_for_addr[0] pr.Add(new NoReferencesForInvocation(fingerprint, graph.getWorkbookName())); continue; } PreList prelist = null; try { // generate prelist prelist = makePreList(g, fingerprint, edatas, graph); } catch (Exception) { // sometimes aliasing bugs pop up; if that happens, move on pr.Add(new AliasingDetected(fingerprint, graph.getWorkbookName())); continue; } // convert an arbitrary instance of this 'function' try { var fpcore = convertToFPCore(g, fingerprint, edatas, graph, prelist); fpcores.Add(fpcore.ToExpr(0)); } catch (Exception e) { // we can't convert everything; give up pr.Add(new CannotConvertExpression(fingerprint, graph.getWorkbookName(), e.Message)); } } return fpcores.ToArray(); }
private static ExpressionTools.EData inlineExpression(AST.Address addr, Depends.DAG graph, MemoDBOpt memodb) { // get top-level AST var ast = graph.getASTofFormulaAt(addr); // merge subtrees return ExpressionTools.flattenExpression(ast, graph, memodb); }
private Dictionary <List <AST.Address>, FPCoreOption> newConvertFormulaGroups( Dictionary <Countable, List <AST.Address> > grps, Dictionary <AST.Address, ExpressionTools.EData> fexprs, Depends.DAG graph, bool showProgress) { throw new Exception("heh"); }
// gets the set of shallow intransitive mixed input vectors pointed to by the formula private static Tuple <int, int, int>[] getSIMIVs(AST.Address formula, Depends.DAG dag) { var vs = ExceLint.Vector.getRebasedVectors(formula, dag, isMixed: true, isTransitive: false, isFormula: true, isOffSheetInsensitive: true, isRelative: true, includeConstant: false); return(vs.Select(v => { if (v.IsConstant) { var c = (ExceLint.Vector.RelativeVector.Constant)v; return new Tuple <int, int, int>(c.Item1, c.Item2, c.Item3); } else { var c = (ExceLint.Vector.RelativeVector.NoConstant)v; return new Tuple <int, int, int>(c.Item1, c.Item2, c.Item3); } }).ToArray()); }
private void extractTest_Click(object sender, RibbonControlEventArgs e) { // get dependence graph var graph = new Depends.DAG(getWorkbook(), getApp(), ignore_parse_errors: false, dagBuilt: new DateTime()); // get all formulas var formulas = getAllFormulas(graph, showProgress: true); // keep track of problem reports var prs = new List <ExtractionLogic.ProblemReport>(); // extract all var fpcores = ExtractionLogic.Extract.extractAll(graph, formulas, prs); var output = String.Join("\n\n", fpcores); System.Windows.Forms.MessageBox.Show(output); }
public BasicTests() { _addressModeDAG = AddressModeDAG(); }
private static PreList makePreList(Group g, Fingerprint fingerprint, Dictionary<Source, ExpressionTools.EData> edatas, Depends.DAG graph) { // produce prelist var prelist = new PreList(); foreach (var f_invocations in g.Functions[fingerprint]) { var bindings = new Dictionary<string, double>(); foreach (var vectref in f_invocations) { var ref_resultant = ExceLint.Vector.RelativeVector(vectref.Head, vectref.Tail, graph); // not every vector gets a variable (e.g., vectors that point to functions); // if so, move on if (g.Variables[fingerprint].ContainsKey(ref_resultant)) { var variable = g.Variables[fingerprint][ref_resultant]; // only bind values to variables if a reference refers // to data, not a formula if (edatas[vectref.Tail].Data.ContainsKey(vectref.Head)) { var value = edatas[vectref.Tail].Data[vectref.Head]; // have we already bound a variable to this value? if (bindings.ContainsKey(variable)) { // it had better be the same value, dude if (bindings[variable] != value) { throw new Exception("Same reference bound to different value!"); } else { continue; } } bindings.Add(variable, value); } } } prelist.Add(bindings); } return prelist; }