Ejemplo n.º 1
0
		/// <summary>
		/// Insert code to unwrap the computed value of a cell, if the cell 
		/// has type Value but is referred to as a Number more than once.
		/// Also register the unwrapped version of the variable 
		/// in the NumberVariables dictionary.
		/// CodeGenerate.Initialize(ilg) must be called first.
		/// </summary>
		public void CreateUnwrappedNumberCells() {
			HashBag<FullCellAddr> numberUses = CountNumberUses();
			foreach (KeyValuePair<FullCellAddr, int> numberUseCount in numberUses.ItemMultiplicities()) {
				FullCellAddr fca = numberUseCount.Key;
				if (numberUseCount.Value >= 2 && addressToVariable[fca].Type == Typ.Value) {
					Variable numberVar = new LocalVariable(fca + "_number", Typ.Number);
					ComputeCell ccell;
					if (fcaToComputeCell.TryGetValue(fca, out ccell)) // fca is ordinary computed cell
					{
						ccell.NumberVar = numberVar;
					}
					else // fca is an input cell
					{
						unwrapInputCells.Add(new UnwrapInputCell(addressToVariable[fca], numberVar));
					}
					NumberVariables.Add(fca, numberVar);
				}
			}
		}
Ejemplo n.º 2
0
		/// <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));
		}