Ejemplo n.º 1
0
        public static void CreateFunction(string name, FullCellAddr outputCell, FullCellAddr[] inputCells)
        {
            name = name.ToUpper();
            // If the function exists, with the same input and output cells, keep it.
            // If it is a placeholder, overwrite its applier; if its input and output
            // cells have changed, recreate it (including its SdfInfo record).
            Function oldFunction = Function.Get(name);

            if (oldFunction != null)
            {
                if (!oldFunction.IsPlaceHolder)
                {
                    return;
                }
            }
            // Registering the function before compilation allows it to call itself recursively
            SdfInfo sdfInfo = Register(outputCell, inputCells, name);

            // Console.WriteLine("Compiling {0} as #{1}", name, info.index);
            Update(sdfInfo, CompileSdf(sdfInfo));
            if (oldFunction != null)             // ... and is not a placeholder
            {
                oldFunction.UpdateApplier(sdfInfo.Apply, sdfInfo.IsVolatile);
            }
            else
            {
                new Function(name, sdfInfo.Apply, isVolatile: sdfInfo.IsVolatile);
            }
        }
Ejemplo n.º 2
0
        // Register, unregister, update and look up the SDF tables

        /// <summary>
        /// Allocate an index for a new SDF, but do not bind its SdfDelegate
        /// </summary>
        /// <param name="outputCell"></param>
        /// <param name="inputCells"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static SdfInfo Register(FullCellAddr outputCell, FullCellAddr[] inputCells, string name)
        {
            name = name.ToUpper();
            SdfInfo sdfInfo = GetInfo(name);

            if (sdfInfo == null)               // New SDF, register it
            {
                sdfInfo = new SdfInfo(outputCell, inputCells, name, nextIndex++);
                Debug.Assert(sdfInfo.index == nextIndex - 1);
                sdfNameToInfo[name] = sdfInfo;
                if (sdfInfo.index >= sdfDelegates.Length)
                {
                    Debug.Assert(sdfDelegates.Length == sdfInfos.Length);
                    // Reallocate sdfDelegates array
                    Delegate[] newSdfs = new Delegate[2 * sdfDelegates.Length];
                    Array.Copy(sdfDelegates, newSdfs, sdfDelegates.Length);
                    sdfDelegates = newSdfs;
                    // Reallocate sdfInfos array
                    SdfInfo[] newSdfInfos = new SdfInfo[2 * sdfInfos.Length];
                    Array.Copy(sdfInfos, newSdfInfos, sdfInfos.Length);
                    sdfInfos = newSdfInfos;
                }
                sdfInfos[sdfInfo.index] = sdfInfo;
                // Update SDF function listbox if created and visible
                SdfForm sdfForm = System.Windows.Forms.Application.OpenForms["sdf"] as SdfForm;
                if (sdfForm != null && sdfForm.Visible)
                {
                    sdfForm.PopulateFunctionListBox(false);
                    sdfForm.PopulateFunctionListBox(name);
                    sdfForm.Invalidate();
                }
            }
            return(sdfInfo);
        }
Ejemplo n.º 3
0
 public static void ShowIL(SdfInfo info) {
   MethodInfo mif = sdfDelegates[info.index].Method;
   ClrTest.Reflection.MethodBodyViewer viewer = new ClrTest.Reflection.MethodBodyViewer();
   viewer.Text = info.ToString();
   viewer.SetMethodBase(mif);
   viewer.ShowDialog();
 }
Ejemplo n.º 4
0
 /// <summary>
 /// Generate code again for the given SDF with unchanged input and output cells,
 /// recreate the corresponding Function, and update the delegate table entry
 /// </summary>
 /// <param name="info"></param>
 // TODO: This should *not* be applied to SDF's resulting from partial evaluation.
 public static void Regenerate(SdfInfo info)
 {
     cellToFunctionMapper.RemoveFunction(info);
     // Removing the SDF from Function enables CreateFunction to overwrite it
     Function.Remove(info.name);
     // Rebuild and add it back
     CreateFunction(info.name, info.outputCell, info.inputCells);
 }
Ejemplo n.º 5
0
        public static void Regenerate(String name)
        {
            SdfInfo info = GetInfo(name);

            if (info != null)
            {
                Regenerate(info);
            }
        }
Ejemplo n.º 6
0
		public static Delegate CreateSdfDelegate(SdfInfo sdfInfo, DependencyGraph dpGraph, IList<FullCellAddr> cellList) {
			Debug.Assert(sdfInfo.inputCells == dpGraph.inputCells);
			Debug.Assert(sdfInfo.outputCell == dpGraph.outputCell);
			ProgramLines program = new ProgramLines(sdfInfo.outputCell, sdfInfo.inputCells);
			program.AddComputeCells(dpGraph, cellList);
			// TODO: This is not the final program, so order may not respect eval cond dependencies!
			sdfInfo.Program = program; // Save ComputeCell list for later partial evaluation
			return program.CompileToDelegate(sdfInfo);
		}
Ejemplo n.º 7
0
        public static void ShowIL(SdfInfo info)
        {
            MethodInfo mif = sdfDelegates[info.index].Method;

            ClrTest.Reflection.MethodBodyViewer viewer = new ClrTest.Reflection.MethodBodyViewer();
            viewer.Text = info.ToString();
            viewer.SetMethodBase(mif);
            viewer.ShowDialog();
        }
Ejemplo n.º 8
0
        public static Delegate CreateSdfDelegate(SdfInfo sdfInfo, DependencyGraph dpGraph, IList <FullCellAddr> cellList)
        {
            Debug.Assert(sdfInfo.inputCells == dpGraph.inputCells);
            Debug.Assert(sdfInfo.outputCell == dpGraph.outputCell);
            ProgramLines program = new ProgramLines(sdfInfo.outputCell, sdfInfo.inputCells);

            program.AddComputeCells(dpGraph, cellList);
            // TODO: This is not the final program, so order may not respect eval cond dependencies!
            sdfInfo.Program = program;             // Save ComputeCell list for later partial evaluation
            return(program.CompileToDelegate(sdfInfo));
        }
Ejemplo n.º 9
0
        public static void DeleteFunction(string methodName)
        {
            SdfInfo info = GetInfo(methodName);

            if (info != null)
            {
                Unregister(info);
                cellToFunctionMapper.RemoveFunction(info);
                Function.Remove(methodName);
            }
        }
Ejemplo n.º 10
0
		internal void RemoveFunction(SdfInfo info) {
			inputCellBag.RemoveAll(info.inputCells);
			outputCellBag.Remove(info.outputCell);
			List<FullCellAddr> addresses;
			if (!functionToAddressList.TryGetValue(info.name, out addresses)) {
				return;
			}
			foreach (FullCellAddr addr in addresses) {
				addressToFunctionList.Remove(addr);
			}
			functionToAddressList.Remove(info.name);
		}
Ejemplo n.º 11
0
 internal void AddFunction(SdfInfo info, ICollection<FullCellAddr> addrs)
 {
     HashSet<FullCellAddr> inputCellSet = new HashSet<FullCellAddr>();
       inputCellSet.UnionWith(info.inputCells);
       foreach (FullCellAddr addr in addrs)
     if (!inputCellSet.Contains(addr))
       AddCellToFunction(info.name, addr);
       List<FullCellAddr> addrsList = new List<FullCellAddr>(addrs);
       functionToAddressList[info.name] = addrsList;
       inputCellBag.AddAll(info.inputCells);
       outputCellBag.Add(info.outputCell);
 }
Ejemplo n.º 12
0
		public Delegate CompileToDelegate(SdfInfo sdfInfo) {
			Debug.Assert(sdfInfo.Program == this); // Which is silly, lots of redundancy
			// Create dynamic method with signature: Value CGMethod(Value, Value, ...) in class Function:
			DynamicMethod method = new DynamicMethod("CGMethod",
													 Value.type,
													 sdfInfo.MyArgumentTypes,
													 Function.type,
													 true);
			ILGenerator ilg = method.GetILGenerator();
			CodeGenerate.Initialize(ilg);
			sdfInfo.Program.EvalCondReorderCompile();
			ilg.Emit(OpCodes.Ret);
			return method.CreateDelegate(sdfInfo.MyType);
		}
Ejemplo n.º 13
0
        /// <summary>
        /// Compiles entry code and body of a sheet-defined function
        /// </summary>
        /// <param name="info">The SdfInfo object describing the function</param>
        /// <returns></returns>
        private static Delegate CompileSdf(SdfInfo info)
        {
            // Build dependency graph containing all cells needed by the output cell
            DependencyGraph dpGraph = new DependencyGraph(info.outputCell,
                                                          info.inputCells,
                                                          delegate(FullCellAddr fca) { return(fca.sheet[fca.ca]); });
            // Topologically sort the graph in calculation order; leave out constants
            IList <FullCellAddr> cellList = dpGraph.PrecedentOrder();

            info.SetVolatility(cellList);
            // Convert each Expr into a CGExpr while preserving order.  Inline single-use expressions
            cellToFunctionMapper.AddFunction(info, dpGraph.GetAllNodes());
            return(ProgramLines.CreateSdfDelegate(info, dpGraph, cellList));
        }
Ejemplo n.º 14
0
        internal void RemoveFunction(SdfInfo info)
        {
            inputCellBag.RemoveAll(info.inputCells);
            outputCellBag.Remove(info.outputCell);
            List <FullCellAddr> addresses;

            if (!functionToAddressList.TryGetValue(info.name, out addresses))
            {
                return;
            }
            foreach (FullCellAddr addr in addresses)
            {
                addressToFunctionList.Remove(addr);
            }
            functionToAddressList.Remove(info.name);
        }
Ejemplo n.º 15
0
        public Delegate CompileToDelegate(SdfInfo sdfInfo)
        {
            Debug.Assert(sdfInfo.Program == this);             // Which is silly, lots of redundancy
            // Create dynamic method with signature: Value CGMethod(Value, Value, ...) in class Function:
            DynamicMethod method = new DynamicMethod("CGMethod",
                                                     Value.type,
                                                     sdfInfo.MyArgumentTypes,
                                                     Function.type,
                                                     true);
            ILGenerator ilg = method.GetILGenerator();

            CodeGenerate.Initialize(ilg);
            sdfInfo.Program.EvalCondReorderCompile();
            ilg.Emit(OpCodes.Ret);
            return(method.CreateDelegate(sdfInfo.MyType));
        }
Ejemplo n.º 16
0
        private CGSdfCall Specialize(CGExpr[] res, Value[] args)
        {
            FunctionValue fv          = new FunctionValue(sdfInfo, args);
            SdfInfo       residualSdf = SdfManager.SpecializeAndCompile(fv);

            CGExpr[] residualArgs = new CGExpr[fv.Arity];
            int      j            = 0;

            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] == ErrorValue.naError)
                {
                    residualArgs[j++] = res[i];
                }
            }
            return(new CGSdfCall(residualSdf, residualArgs));
        }
Ejemplo n.º 17
0
        internal void AddFunction(SdfInfo info, ICollection <FullCellAddr> addrs)
        {
            HashSet <FullCellAddr> inputCellSet = new HashSet <FullCellAddr>();

            inputCellSet.UnionWith(info.inputCells);
            foreach (FullCellAddr addr in addrs)
            {
                if (!inputCellSet.Contains(addr))
                {
                    AddCellToFunction(info.name, addr);
                }
            }
            List <FullCellAddr> addrsList = new List <FullCellAddr>(addrs);

            functionToAddressList[info.name] = addrsList;
            inputCellBag.AddAll(info.inputCells);
            outputCellBag.Add(info.outputCell);
        }
Ejemplo n.º 18
0
		public FunctionValue(SdfInfo sdfInfo, Value[] args) {
			this.sdfInfo = sdfInfo;
			// A null or empty args array is equivalent to an array of all NA
			if (args == null || args.Length == 0) {
				args = new Value[sdfInfo.arity];
				for (int i = 0; i < args.Length; i++) {
					args[i] = ErrorValue.naError;
				}
			}
			// Requirement: There will be no further writes to the args array
			this.args = args;
			int k = 0;
			for (int i = 0; i < args.Length; i++) {
				if (args[i] == ErrorValue.naError) {
					k++;
				}
			}
			this.arity = k;
			this.mergeAndCall = MakeMergeAndCallMethod();
		}
Ejemplo n.º 19
0
        public override void Compile()
        {
            int argCount = es.Length - 1;

            if (es.Length < 1)
            {
                LoadErrorValue(ErrorValue.argCountError);
            }
            else if (es[0] is CGTextConst)
            {
                String  name    = (es[0] as CGTextConst).value.value;
                SdfInfo sdfInfo = SdfManager.GetInfo(name);
                if (sdfInfo == null)
                {
                    LoadErrorValue(ErrorValue.nameError);
                }
                else if (argCount != 0 && argCount != sdfInfo.arity)
                {
                    LoadErrorValue(ErrorValue.argCountError);
                }
                else
                {
                    ilg.Emit(OpCodes.Ldc_I4, sdfInfo.index);
                    CompileToValueArray(argCount, 1, es);
                    ilg.Emit(OpCodes.Call, FunctionValue.makeMethod);
                }
            }
            else
            {
                es[0].Compile();
                CheckType(FunctionValue.type,
                          new Gen(delegate {
                    CompileToValueArray(argCount, 1, es);
                    ilg.Emit(OpCodes.Call, FunctionValue.furtherApplyMethod);
                }),
                          GenLoadErrorValue(ErrorValue.argTypeError));
            }
        }
Ejemplo n.º 20
0
		public CGSdfCall(SdfInfo sdfInfo, CGExpr[] es)
			: base(es, null) {
			this.sdfInfo = sdfInfo;
		}
Ejemplo n.º 21
0
    // Register, unregister, update and look up the SDF tables

    /// <summary>
    /// Allocate an index for a new SDF, but do not bind its SdfDelegate
    /// </summary>
    /// <param name="outputCell"></param>
    /// <param name="inputCells"></param>
    /// <param name="name"></param>
    /// <returns></returns>
    public static SdfInfo Register(FullCellAddr outputCell, FullCellAddr[] inputCells, string name) {
      name = name.ToUpper();
      SdfInfo sdfInfo = GetInfo(name);
      if (sdfInfo == null) { // New SDF, register it
        sdfInfo = new SdfInfo(outputCell, inputCells, name, nextIndex++);
        Debug.Assert(sdfInfo.index == nextIndex - 1);
        sdfNameToInfo[name] = sdfInfo;
        if (sdfInfo.index >= sdfDelegates.Length) {
          Debug.Assert(sdfDelegates.Length == sdfInfos.Length);
          // Reallocate sdfDelegates array
          Delegate[] newSdfs = new Delegate[2 * sdfDelegates.Length];
          Array.Copy(sdfDelegates, newSdfs, sdfDelegates.Length);
          sdfDelegates = newSdfs;
          // Reallocate sdfInfos array
          SdfInfo[] newSdfInfos = new SdfInfo[2 * sdfInfos.Length];
          Array.Copy(sdfInfos, newSdfInfos, sdfInfos.Length);
          sdfInfos = newSdfInfos;
        }
        sdfInfos[sdfInfo.index] = sdfInfo;
        // Update SDF function listbox if created and visible 
        GUI.SdfForm sdfForm = System.Windows.Forms.Application.OpenForms["sdf"] as GUI.SdfForm;
        if (sdfForm != null && sdfForm.Visible) {
          sdfForm.PopulateFunctionListBox(false);
          sdfForm.PopulateFunctionListBox(name);
          sdfForm.Invalidate();
        }
      }
      return sdfInfo;
    }
Ejemplo n.º 22
0
 private static void Update(SdfInfo info, Delegate method) {
   sdfDelegates[info.index] = method;
 }
Ejemplo n.º 23
0
 private static void Unregister(SdfInfo info) {
   sdfNameToInfo.Remove(info.name);
   sdfDelegates[info.index] = sdfDeleted[info.arity];
   sdfInfos[info.index] = null;
 }
Ejemplo n.º 24
0
 /// <summary>
 /// Generate code again for the given SDF with unchanged input and output cells, 
 /// recreate the corresponding Function, and update the delegate table entry
 /// </summary>
 /// <param name="info"></param>
 // TODO: This should *not* be applied to SDF's resulting from partial evaluation.
 public static void Regenerate(SdfInfo info) {
   cellToFunctionMapper.RemoveFunction(info);
   // Removing the SDF from Function enables CreateFunction to overwrite it
   Function.Remove(info.name);
   // Rebuild and add it back
   CreateFunction(info.name, info.outputCell, info.inputCells);
 }
Ejemplo n.º 25
0
 private static void Unregister(SdfInfo info)
 {
     sdfNameToInfo.Remove(info.name);
     sdfDelegates[info.index] = sdfDeleted[info.arity];
     sdfInfos[info.index]     = null;
 }
Ejemplo n.º 26
0
 private static void Update(SdfInfo info, Delegate method)
 {
     sdfDelegates[info.index] = method;
 }
Ejemplo n.º 27
0
 /// <summary>
 /// Compiles entry code and body of a sheet-defined function
 /// </summary>
 /// <param name="info">The SdfInfo object describing the function</param>
 /// <returns></returns>
 private static Delegate CompileSdf(SdfInfo info) {
   // Build dependency graph containing all cells needed by the output cell
   DependencyGraph dpGraph = new DependencyGraph(info.outputCell, info.inputCells,
     delegate(FullCellAddr fca) { return fca.sheet[fca.ca]; });
   // Topologically sort the graph in calculation order; leave out constants
   IList<FullCellAddr> cellList = dpGraph.PrecedentOrder();
   info.SetVolatility(cellList);
   // Convert each Expr into a CGExpr while preserving order.  Inline single-use expressions
   cellToFunctionMapper.AddFunction(info, dpGraph.GetAllNodes());
   return ProgramLines.CreateSdfDelegate(info, dpGraph, cellList);  
 }
Ejemplo n.º 28
0
 public CGSdfCall(SdfInfo sdfInfo, CGExpr[] es)
     : base(es, null)
 {
     this.sdfInfo = sdfInfo;
 }
Ejemplo n.º 29
0
        public static CGExpr Make(String name, CGExpr[] es)
        {
            name = name.ToUpper();
            // This switch should agree with the function table in Functions.cs
            switch (name)
            {
            case "+":
                return(new CGArithmetic2(OpCodes.Add, name, es));

            case "*":
                return(new CGArithmetic2(OpCodes.Mul, name, es));

            case "-":
                return(new CGArithmetic2(OpCodes.Sub, name, es));

            case "/":
                return(new CGArithmetic2(OpCodes.Div, name, es));

            case "=":
                return(CGEqual.Make(es));

            case "<>":
                return(CGNotEqual.Make(es));

            case ">":
                return(new CGGreaterThan(es));

            case "<=":
                return(new CGLessThanOrEqual(es));

            case "<":
                return(new CGLessThan(es));

            case ">=":
                return(new CGGreaterThanOrEqual(es));

            // Non-strict, or other special treatment
            case "AND":
                return(new CGAnd(es));

            case "APPLY":
                return(new CGApply(es));

            case "CHOOSE":
                return(new CGChoose(es));

            case "CLOSURE":
                return(new CGClosure(es));

            case "ERR":
                return(new CGError(es));

            case "EXTERN":
                return(new CGExtern(es));

            case "IF":
                return(new CGIf(es));

            case "NA":
                if (es.Length == 0)
                {
                    return(new CGError(ErrorValue.naError));
                }
                else
                {
                    return(new CGError(ErrorValue.argCountError));
                }

            case "NEG":
                return(new CGNeg(es));

            case "NOT":
                return(new CGNot(es));

            case "OR":
                return(new CGOr(es));

            case "PI":
                if (es.Length == 0)
                {
                    return(new CGNumberConst(NumberValue.PI));
                }
                else
                {
                    return(new CGError(ErrorValue.argCountError));
                }

            case "VOLATILIZE":
                if (es.Length == 1)
                {
                    return(es[0]);
                }
                else
                {
                    return(new CGError(ErrorValue.argCountError));
                }

            default:
                // The general case for most built-in functions with unspecific argument types
                FunctionInfo functionInfo;
                if (FunctionInfo.Find(name, out functionInfo))
                {
                    return(new CGFunctionCall(functionInfo, es));
                }
                else                           // May be a sheet-defined function
                {
                    SdfInfo sdfInfo = SdfManager.GetInfo(name);
                    if (sdfInfo != null)
                    {
                        return(new CGSdfCall(sdfInfo, es));
                    }
                    else
                    {
                        return(new CGError(ErrorValue.nameError));
                    }
                }
            }
        }