public static CGExpr BuildExpression(FullCellAddr addr, Dictionary<FullCellAddr, Variable> addressToVariable) { Cell cell; if (!addr.TryGetCell(out cell)) { return new CGTextConst(TextValue.EMPTY); } else if (cell is NumberCell) { return new CGNumberConst(((NumberCell)cell).value); } else if (cell is TextCell) { return new CGTextConst(((TextCell)cell).value); } else if (cell is QuoteCell) { return new CGTextConst(((QuoteCell)cell).value); } else if (cell is BlankCell) { return new CGError("#FUNERR: Blank cell in function"); } else if (cell is Formula) { // Translate the expr relative to its containing cell at addr CGExpressionBuilder cgBuilder = new CGExpressionBuilder(addressToVariable, addr); Expr expr = ((Formula)cell).Expr; expr.VisitorCall(cgBuilder); return cgBuilder.result; } else if (cell is ArrayFormula) { return new CGError("#FUNERR: Array formula in function"); } else { throw new ImpossibleException("BuildExpression: " + cell); } }
/// <summary> /// Compiles the topologically sorted list of Expr to a list (program) /// of ComputeCells, encapsulating CGExprs. Builds a map from cellAddr to /// local variable ids, for compiling sheet-internal cellrefs to ldloc instructions. /// </summary> public void AddComputeCells(DependencyGraph dpGraph, IList <FullCellAddr> cellList) { Debug.Assert(dpGraph.outputCell == cellList[cellList.Count - 1]); CGExpr outputExpr; if (cellList.Count == 0 || cellList.Count == 1 && dpGraph.inputCellSet.Contains(cellList.Single())) { // The output cell is also an input cell; load it: outputExpr = new CGCellRef(dpGraph.outputCell, addressToVariable[dpGraph.outputCell]); } else { // First process all non-output cells, and ignore all input cells: foreach (FullCellAddr cellAddr in cellList) { if (cellAddr.Equals(dpGraph.outputCell)) { continue; } HashSet <FullCellAddr> dependents = dpGraph.GetDependents(cellAddr); int minUses = dependents.Count; if (minUses == 1) { FullCellAddr fromFca = dependents.First(); minUses = Math.Max(minUses, GetCount(fromFca, cellAddr)); } // Now if minUses==1 then there is at most one use of the cell at cellAddr, // and no local variable is needed. Otherwise, allocate a local variable: if (minUses > 1) { CGExpr newExpr = CGExpressionBuilder.BuildExpression(cellAddr, addressToVariable); Variable var = new LocalVariable(cellAddr.ToString(), newExpr.Type()); AddComputeCell(cellAddr, new ComputeCell(newExpr, var, cellAddr)); } } // Then process the output cell: outputExpr = CGExpressionBuilder.BuildExpression(dpGraph.outputCell, addressToVariable); } // Add the output cell expression last, without a variable to bind it to; hence the null, // also indicating that (only) the output cell is in tail position: AddComputeCell(dpGraph.outputCell, new ComputeCell(outputExpr, null, dpGraph.outputCell)); }
public static CGExpr BuildExpression(FullCellAddr addr, Dictionary <FullCellAddr, Variable> addressToVariable) { Cell cell; if (!addr.TryGetCell(out cell)) { return(new CGTextConst(TextValue.EMPTY)); } else if (cell is NumberCell) { return(new CGNumberConst(((NumberCell)cell).value)); } else if (cell is TextCell) { return(new CGTextConst(((TextCell)cell).value)); } else if (cell is QuoteCell) { return(new CGTextConst(((QuoteCell)cell).value)); } else if (cell is BlankCell) { return(new CGError("#FUNERR: Blank cell in function")); } else if (cell is Formula) { // Translate the expr relative to its containing cell at addr CGExpressionBuilder cgBuilder = new CGExpressionBuilder(addressToVariable, addr); Expr expr = ((Formula)cell).Expr; expr.VisitorCall(cgBuilder); return(cgBuilder.result); } else if (cell is ArrayFormula) { return(new CGError("#FUNERR: Array formula in function")); } else { throw new ImpossibleException("BuildExpression: " + cell); } }