예제 #1
0
        // Partially evaluate the programList with respect to the given static inputs,
        // producing a new ProgramLines object.
        public ProgramLines PEval(Value[] args, FullCellAddr[] residualInputs)
        {
            PEnv pEnv = new PEnv();

            // Map static input cells to their constant values:
            for (int i = 0; i < args.Length; i++)
            {
                pEnv[inputCells[i]] = CGConst.Make(args[i]);
            }
            ProgramLines residual = new ProgramLines(outputCell, residualInputs);

            // PE-time environment PEnv maps each residual input cell address to the delegate argument:
            for (int i = 0; i < residualInputs.Length; i++)
            {
                FullCellAddr input = residualInputs[i];
                pEnv[input] = new CGCellRef(input, residual.addressToVariable[input]);
            }
            // Process the given function's compute cells in dependency order, output last:
            foreach (ComputeCell ccell in programList)
            {
                ComputeCell rCcell = ccell.PEval(pEnv);
                if (rCcell != null)
                {
                    residual.AddComputeCell(ccell.cellAddr, rCcell);
                }
            }
            residual = residual.PruneZeroUseCells();
            return(residual);
        }
예제 #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));
        }
예제 #3
0
        // Returns residual ComputeCell or null if no cell needed
        public ComputeCell PEval(PEnv pEnv)
        {
            CGExpr rCond = null;

            if (evalCond != null)             // Never the case for an output cell
            {
                rCond = evalCond.PEval(pEnv, false /* not dynamic control */);
            }
            if (rCond is CGNumberConst)
            {
                if ((rCond as CGNumberConst).number.value != 0.0)
                {
                    rCond = null;                     // eval cond constant TRUE, discard eval cond
                }
                else
                {
                    return(null);                    // eval cond constant FALSE, discard entire compute cell
                }
            }
            // If residual eval cond is not TRUE then expr has dynamic control
            CGExpr rExpr = expr.PEval(pEnv, rCond != null);

            if (rExpr is CGConst && var != null)
            {
                // If cell's value is constant and it is not an output cell just put in PEnv
                pEnv[cellAddr] = rExpr;
                return(null);
            }
            else
            {
                // Else create fresh local variable for the residual cell, and make
                // PEnv map cell address to that local variable:
                Variable newVar = var != null?var.Fresh() : null;

                pEnv[cellAddr] = new CGCellRef(cellAddr, newVar);
                ComputeCell result = new ComputeCell(rExpr, newVar, cellAddr);
                // result.EvalCond = rCond;  // Don't save residual eval cond, we compute it accurately later...
                return(result);
            }
        }
예제 #4
0
		// Returns residual ComputeCell or null if no cell needed
		public ComputeCell PEval(PEnv pEnv) {
			CGExpr rCond = null;
			if (evalCond != null) // Never the case for an output cell
			{
				rCond = evalCond.PEval(pEnv, false /* not dynamic control */);
			}
			if (rCond is CGNumberConst) {
				if ((rCond as CGNumberConst).number.value != 0.0) {
					rCond = null; // eval cond constant TRUE, discard eval cond
				}
				else {
					return null; // eval cond constant FALSE, discard entire compute cell
				}
			}
			// If residual eval cond is not TRUE then expr has dynamic control
			CGExpr rExpr = expr.PEval(pEnv, rCond != null);
			if (rExpr is CGConst && var != null) {
				// If cell's value is constant and it is not an output cell just put in PEnv
				pEnv[cellAddr] = rExpr;
				return null;
			}
			else {
				// Else create fresh local variable for the residual cell, and make 
				// PEnv map cell address to that local variable:          
				Variable newVar = var != null ? var.Fresh() : null;
				pEnv[cellAddr] = new CGCellRef(cellAddr, newVar);
				ComputeCell result = new ComputeCell(rExpr, newVar, cellAddr);
				// result.EvalCond = rCond;  // Don't save residual eval cond, we compute it accurately later...
				return result;
			}
		}
예제 #5
0
		// Partially evaluate the programList with respect to the given static inputs, 
		// producing a new ProgramLines object.
		public ProgramLines PEval(Value[] args, FullCellAddr[] residualInputs) {
			PEnv pEnv = new PEnv();
			// Map static input cells to their constant values:
			for (int i = 0; i < args.Length; i++) {
				pEnv[inputCells[i]] = CGConst.Make(args[i]);
			}
			ProgramLines residual = new ProgramLines(outputCell, residualInputs);
			// PE-time environment PEnv maps each residual input cell address to the delegate argument:
			for (int i = 0; i < residualInputs.Length; i++) {
				FullCellAddr input = residualInputs[i];
				pEnv[input] = new CGCellRef(input, residual.addressToVariable[input]);
			}
			// Process the given function's compute cells in dependency order, output last:
			foreach (ComputeCell ccell in programList) {
				ComputeCell rCcell = ccell.PEval(pEnv);
				if (rCcell != null) {
					residual.AddComputeCell(ccell.cellAddr, rCcell);
				}
			}
			residual = residual.PruneZeroUseCells();
			return residual;
		}
예제 #6
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));
		}