Пример #1
0
		public CGExtern(CGExpr[] es)
			: base(es, null) {
			if (es.Length < 1) {
				errorValue = ErrorValue.argCountError;
			}
			else {
				CGTextConst nameAndSignatureConst = es[0] as CGTextConst;
				if (nameAndSignatureConst == null) {
					errorValue = ErrorValue.argTypeError;
				}
				else {
					try {
						// This retrieves the method from cache, or creates it:
						ef = ExternalFunction.Make(nameAndSignatureConst.value.value);
						if (ef.arity != es.Length - 1) {
							ef = null;
							errorValue = ErrorValue.argCountError;
						}
						else {
							resType = FromType(ef.ResType);
							argTypes = new Typ[ef.arity];
							for (int i = 0; i < argTypes.Length; i++) {
								argTypes[i] = FromType(ef.ArgType(i));
							}
						}
					}
					catch (Exception exn) // Covers a multitude of sins
					{
						errorValue = ErrorValue.Make(exn.Message);
					}
				}
			}
		}
Пример #2
0
		public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) {
			// When FunctionValue is known, reduce to a CGSdfCall node.  
			// Don't actually call the function (even on constant arguments); could loop.
			CGExpr[] res = PEvalArgs(pEnv, hasDynamicControl);
			if (res[0] is CGValueConst) {
				FunctionValue fv = (res[0] as CGValueConst).Value as FunctionValue;
				if (fv != null) {
					CGExpr[] args = new CGExpr[fv.args.Length];
					int j = 1;
					for (int i = 0; i < args.Length; i++) {
						if (fv.args[i] != ErrorValue.naError) {
							args[i] = CGConst.Make(fv.args[i]);
						}
						else {
							args[i] = res[j++];
						}
					}
					return new CGSdfCall(fv.sdfInfo, args);
				}
				else {
					return new CGError(ErrorValue.argCountError);
				}
			}
			else {
				return new CGApply(res);
			}
		}
Пример #3
0
        public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl)
        {
            List <CGExpr> res = new List <CGExpr>();

            for (int i = 0; i < es.Length; i++)
            {
                CGExpr ri = es[i].PEval(pEnv, hasDynamicControl || res.Count > 0);
                if (ri is CGNumberConst)
                {
                    // A TRUE operand makes the OR true; a FALSE operand can be ignored
                    if ((ri as CGNumberConst).number.value != 0.0)
                    {
                        return(new CGNumberConst(NumberValue.ONE));
                    }
                }
                else
                {
                    res.Add(ri);
                }
            }
            // The residual OR consists of the non-constant operands, if any
            if (res.Count == 0)
            {
                return(new CGNumberConst(NumberValue.ZERO));
            }
            else
            {
                return(new CGOr(res.ToArray()));
            }
        }
Пример #4
0
		public CGExpr[] PEvalArgs(PEnv pEnv, bool hasDynamicControl) {
			CGExpr[] res = new CGExpr[es.Length];
			for (int i = 0; i < es.Length; i++) {
				res[i] = es[i].PEval(pEnv, hasDynamicControl);
			}
			return res;
		}
Пример #5
0
 public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl)
 {
     // When FunctionValue is known, reduce to a CGSdfCall node.
     // Don't actually call the function (even on constant arguments); could loop.
     CGExpr[] res = PEvalArgs(pEnv, hasDynamicControl);
     if (res[0] is CGValueConst)
     {
         FunctionValue fv = (res[0] as CGValueConst).Value as FunctionValue;
         if (fv != null)
         {
             CGExpr[] args = new CGExpr[fv.args.Length];
             int      j    = 1;
             for (int i = 0; i < args.Length; i++)
             {
                 if (fv.args[i] != ErrorValue.naError)
                 {
                     args[i] = CGConst.Make(fv.args[i]);
                 }
                 else
                 {
                     args[i] = res[j++];
                 }
             }
             return(new CGSdfCall(fv.sdfInfo, args));
         }
         else
         {
             return(new CGError(ErrorValue.argCountError));
         }
     }
     else
     {
         return(new CGApply(res));
     }
 }
Пример #6
0
		// Reductions such as 0*e==>0 are a bit dubious when you 
		// consider that e could evaluate to ArgType error or similar:
		public CGExpr Make(CGExpr[] es) {
			if (es.Length == 2) {
				if (op == "+" && es[0].Is(0)) {
					return es[1]; // 0+e = e
				}
				else if ((op == "+" || op == "-") && es[1].Is(0)) {
					return es[0]; // e+0 = e-0 = e
				}
				else if (op == "-" && es[0].Is(0)) {
					return new CGNeg(new CGExpr[] {es[1]}); // 0-e = -e
				}
				else if (op == "*" && (es[0].Is(0) || es[1].Is(0))) {
					return new CGNumberConst(NumberValue.ZERO); // 0*e = e*0 = 0 (**)
				}
				else if (op == "*" && es[0].Is(1)) {
					return es[1]; // 1*e = e
				}
				else if ((op == "*" || op == "/") && es[1].Is(1)) {
					return es[0]; // e*1 = e/1 = e
				}
				else if (op == "^" && (es[0].Is(1) || es[1].Is(1))) {
					return es[0]; // e^1 = e and also 1^e = 1 (IEEE)
				}
				else if (op == "^" && es[1].Is(0)) {
					return new CGNumberConst(NumberValue.ONE); // e^0 = 1 (IEEE)
				}
			}
			return new CGArithmetic2(opCode, op, es);
		}
Пример #7
0
 public CGCachedExpr(CGExpr expr, CachedAtom cachedAtom, List <CGCachedExpr> caches)
 {
     this.expr        = expr;
     this.cachedAtom  = cachedAtom;
     this.cacheNumber = caches.Count;
     caches.Add(this);
 }
Пример #8
0
		public bool AllConstant(CGExpr[] res) {
			for (int i = 0; i < res.Length; i++) {
				if (!(res[i] is CGConst)) {
					return false;
				}
			}
			return true;
		}
Пример #9
0
 public CGExpr[] PEvalArgs(PEnv pEnv, bool hasDynamicControl)
 {
     CGExpr[] res = new CGExpr[es.Length];
     for (int i = 0; i < es.Length; i++)
     {
         res[i] = es[i].PEval(pEnv, hasDynamicControl);
     }
     return(res);
 }
Пример #10
0
		private Variable numberVar; // If non-null, unwrap to this Number variable
		// If var==null then numberVar==null

		public ComputeCell(CGExpr expr, Variable var, FullCellAddr cellAddr) {
			this.expr = expr;
			this.var = var;
			// The output cell's expression is in tail position:
			if (var == null) {
				this.expr.NoteTailPosition();
			}
			this.cellAddr = cellAddr;
			this.numberVar = null;
		}
Пример #11
0
 public void CallVisitor(FunCall funCall)
 {
     CGExpr[] expressions = new CGExpr[funCall.es.Length];
     for (int i = 0; i < funCall.es.Length; i++)
     {
         funCall.es[i].VisitorCall(this);
         expressions[i] = result;
     }
     result = CGComposite.Make(funCall.function.name, expressions);
 }
Пример #12
0
 public override void CompileCondition(Gen ifTrue, Gen ifFalse, Gen ifOther)
 {
     for (int i = es.Length - 1; i >= 0; i--)
     {
         // These declarations are needed to capture rvalues rather than lvalues:
         CGExpr ei           = es[i];
         Gen    localIfFalse = ifFalse;
         ifFalse = new Gen(delegate { ei.CompileCondition(ifTrue, localIfFalse, ifOther); });
     }
     ifFalse.Generate(ilg);
 }
Пример #13
0
        private Variable numberVar;      // If non-null, unwrap to this Number variable
        // If var==null then numberVar==null

        public ComputeCell(CGExpr expr, Variable var, FullCellAddr cellAddr)
        {
            this.expr = expr;
            this.var  = var;
            // The output cell's expression is in tail position:
            if (var == null)
            {
                this.expr.NoteTailPosition();
            }
            this.cellAddr  = cellAddr;
            this.numberVar = null;
        }
Пример #14
0
		public static CGExpr Make(CGExpr[] es) {
			if (es.Length == 2) {
				if (es[0].Is(0)) // 0.0<>e1 ==> AND(e1)
				{
					return new CGAnd(new CGExpr[] {es[1]});
				}
				else if (es[1].Is(0)) // e0<>0.0 ==> AND(e0)
				{
					return new CGAnd(new CGExpr[] {es[0]});
				}
			}
			return new CGNotEqual(es);
		}
Пример #15
0
		public static CGExpr Make(CGExpr[] es) {
			if (es.Length == 2) {
				if (es[0].Is(0)) // 0.0=e1 ==> NOT(e1)
				{
					return new CGNot(new CGExpr[] {es[1]});
				}
				else if (es[1].Is(0)) // e0=0.0 ==> NOT(e0)
				{
					return new CGNot(new CGExpr[] {es[0]});
				}
			}
			return new CGEqual(es);
		}
Пример #16
0
		// This is used to implement the ERR function
		public CGError(CGExpr[] es) {
			if (es.Length != 1) {
				errorValue = ErrorValue.argCountError;
			}
			else {
				CGTextConst messageConst = es[0] as CGTextConst;
				if (messageConst == null) {
					errorValue = ErrorValue.argTypeError;
				}
				else {
					errorValue = ErrorValue.Make("#ERR: " + messageConst.value.value);
				}
			}
		}
Пример #17
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));
        }
Пример #18
0
 public override void EvalCond(PathCond evalCond,
                               IDictionary <FullCellAddr, PathCond> evalConds,
                               List <CGCachedExpr> caches)
 {
     if (es.Length >= 1)
     {
         CachedAtom   atom   = new CachedAtom(es[0], caches);
         CGCachedExpr cached = atom.cachedExpr;
         es[0].EvalCond(evalCond, evalConds, caches);
         es[0] = cached;
         for (int i = 1; i < es.Length; i++)
         {
             CGExpr iConst = CGConst.Make(i);
             CGExpr cond   = new CGEqual(new CGExpr[] { cached, iConst });
             es[i].EvalCond(evalCond.And(new CachedAtom(cond, caches)), evalConds, caches);
         }
     }
 }
Пример #19
0
        public void CallVisitor(CellRef cellRef)
        {
            FullCellAddr cellAddr = cellRef.GetAbsoluteAddr(thisFca);

            if (cellAddr.sheet != thisFca.sheet)
            {
                // Reference to other sheet, hopefully a normal sheet
                result = new CGNormalCellRef(cellAddr);
            }
            else if (this.addressToVariable.ContainsKey(cellAddr))
            {
                // Reference to a cell that has already been computed in a local variable
                result = new CGCellRef(cellAddr, this.addressToVariable[cellAddr]);
            }
            else             // Inline the cell's formula's expression
            {
                result = BuildExpression(cellAddr, addressToVariable);
            }
        }
Пример #20
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));
        }
Пример #21
0
        public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl)
        {
            CGExpr r0 = es[0].PEval(pEnv, hasDynamicControl);

            if (r0 is CGNumberConst)
            {
                if ((r0 as CGNumberConst).number.value != 0.0)
                {
                    return(es[1].PEval(pEnv, hasDynamicControl));
                }
                else
                {
                    return(es[2].PEval(pEnv, hasDynamicControl));
                }
            }
            else
            {
                return(new CGIf(PEvalArgs(pEnv, r0, true)));
            }
        }
Пример #22
0
        public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl)
        {
            CGExpr r0 = es[0].PEval(pEnv, hasDynamicControl);

            if (r0 is CGNumberConst)
            {
                int index = (int)((r0 as CGNumberConst).number.value);
                if (index < 1 || index >= es.Length)
                {
                    return(new CGError(ErrorValue.valueError));
                }
                else
                {
                    return(es[index].PEval(pEnv, hasDynamicControl));
                }
            }
            else
            {
                return(new CGChoose(PEvalArgs(pEnv, r0, true /* has dynamic control */)));
            }
        }
Пример #23
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);
            }
        }
Пример #24
0
		public CGSdfCall(SdfInfo sdfInfo, CGExpr[] es)
			: base(es, null) {
			this.sdfInfo = sdfInfo;
		}
Пример #25
0
 public void CallVisitor(CellArea cellArea)
 {
     result = new CGNormalCellArea(cellArea.MakeArrayView(thisFca));
 }
Пример #26
0
		public override CGExpr Residualize(CGExpr[] res) { return new CGGreaterThan(res); }
Пример #27
0
        // Generate code to evaluate all argument expressions, including the receiver es[1]
        // if the method is an instance method, and convert their values to .NET types.

        private void CompileArgumentsAndApply(CGExpr[] es, Gen ifSuccess, Gen ifOther)
        {
            int argCount = es.Length;

            // The error continuations must pop the arguments computed so far.
            Gen[] errorCont = new Gen[argCount];
            if (argCount > 0)
            {
                errorCont[0] = ifOther;
            }
            for (int i = 1; i < argCount; i++)
            {
                int ii = i;                 // Capture lvalue -- do NOT inline!
                errorCont[ii] = new Gen(delegate {
                    ilg.Emit(OpCodes.Pop);
                    errorCont[ii - 1].Generate(ilg);
                });
            }
            // Generate code, backwards, to evaluate argument expressions and
            // convert to the .NET method's argument types
            for (int i = argCount - 1; i >= 0; i--)
            {
                // These local vars capture rvalue rather than lvalue -- do NOT inline them!
                CGExpr ei           = es[i];
                Gen    localSuccess = ifSuccess;
                Typ    argType      = functionInfo.signature.argTypes[i];
                Gen    ifError      = errorCont[i];
                if (argType == Typ.Number)
                {
                    ifSuccess = new Gen(delegate {
                        ei.CompileToDoubleOrNan();
                        localSuccess.Generate(ilg);
                    });
                }
                else if (argType == Typ.Function)
                {
                    ifSuccess = new Gen(delegate {
                        ei.Compile();
                        CheckType(FunctionValue.type, localSuccess, ifError);
                    });
                }
                else if (argType == Typ.Array)
                {
                    ifSuccess = new Gen(delegate {
                        ei.Compile();
                        CheckType(ArrayValue.type, localSuccess, ifError);
                    });
                }
                else if (argType == Typ.Text)
                {
                    ifSuccess = new Gen(delegate {
                        ei.Compile();
                        CheckType(TextValue.type, localSuccess, ifError);
                    });
                }
                else                 // argType.Value -- TODO: neglects to propagate ErrorValue from argument
                {
                    ifSuccess = new Gen(delegate {
                        ei.Compile();
                        localSuccess.Generate(ilg);
                    });
                }
            }
            ifSuccess.Generate(ilg);
        }
Пример #28
0
 public void CallVisitor(ValueConst valueConst)
 {
     result = new CGValueConst(valueConst.value);
 }
Пример #29
0
		// Generate code to evaluate all argument expressions, including the receiver es[1]
		// if the method is an instance method, and convert their values to .NET types.

		private void CompileArgumentsAndApply(CGExpr[] es, Gen ifSuccess, Gen ifOther) {
			int argCount = es.Length - 1;
			// The error continuations must pop the arguments computed so far:
			Gen[] errorCont = new Gen[argCount];
			if (argCount > 0) {
				errorCont[0] = ifOther;
			}
			for (int i = 1; i < argCount; i++) {
				int ii = i; // Capture lvalue -- do NOT inline!
				errorCont[ii] = new Gen(delegate {
											ilg.Emit(OpCodes.Pop);
											errorCont[ii - 1].Generate(ilg);
										});
			}
			// Generate code, backwards, to evaluate argument expressions and
			// convert to external method's argument types
			for (int i = argCount - 1; i >= 0; i--) {
				// These local vars capture rvalue rather than lvalue -- do NOT inline them!
				CGExpr ei = es[i + 1];
				Gen localSuccess = ifSuccess;
				int argIndex = i;
				Type argType = ef.ArgType(i);
				Gen ifError = errorCont[i];
				// First some special cases to avoid boxing:
				if (argType == typeof (System.Double)) {
					ifSuccess = new Gen(
						delegate {
							ei.CompileToDoubleOrNan();
							localSuccess.Generate(ilg);
						});
				}
				else if (argType == typeof (System.Single)) {
					ifSuccess = new Gen(
						delegate {
							ei.CompileToDoubleOrNan();
							ilg.Emit(OpCodes.Conv_R4);
							localSuccess.Generate(ilg);
						});
				}
				else if (signed32.Contains(argType)) {
					ifSuccess = new Gen(
						delegate {
							ei.CompileToDoubleProper(
													 new Gen(delegate {
																 ilg.Emit(OpCodes.Conv_I4);
																 localSuccess.Generate(ilg);
															 }),
													 ifError);
						});
				}
				else if (unsigned32.Contains(argType)) {
					ifSuccess = new Gen(
						delegate {
							ei.CompileToDoubleProper(
													 new Gen(delegate {
																 ilg.Emit(OpCodes.Conv_U4);
																 localSuccess.Generate(ilg);
															 }),
													 ifError);
						});
				}
				else if (argType == typeof (System.Int64)) {
					ifSuccess = new Gen(
						delegate {
							ei.CompileToDoubleProper(
													 new Gen(delegate {
																 ilg.Emit(OpCodes.Conv_I8);
																 localSuccess.Generate(ilg);
															 }),
													 ifError);
						});
				}
				else if (argType == typeof (System.UInt64)) {
					ifSuccess = new Gen(
						delegate {
							ei.CompileToDoubleProper(
													 new Gen(delegate {
																 ilg.Emit(OpCodes.Conv_U8);
																 localSuccess.Generate(ilg);
															 }),
													 ifError);
						});
				}
				else if (argType == typeof (System.Boolean)) {
					ifSuccess = new Gen(
						delegate {
							ei.CompileToDoubleProper(
													 new Gen(delegate {
																 ilg.Emit(OpCodes.Ldc_R8, 0.0);
																 ilg.Emit(OpCodes.Ceq);
																 localSuccess.Generate(ilg);
															 }),
													 ifError);
						});
				}
				else if (argType == typeof (System.Char)) {
					ifSuccess = new Gen(
						delegate {
							ei.Compile();
							ilg.Emit(OpCodes.Call, TextValue.toNakedCharMethod);
							localSuccess.Generate(ilg);
						});
				}
				else if (argType == typeof (System.String)) {
					ifSuccess = new Gen(
						delegate {
							ei.Compile();
							UnwrapToString(localSuccess, ifError);
						});
				}
				else // General cases: String[], double[], double[,], ...
				{
					ifSuccess = new Gen(
						delegate {
							ei.Compile();
							ilg.Emit(OpCodes.Call, ef.ArgConverter(argIndex).Method);
							if (argType.IsValueType) // must unbox wrapped value type, but this is too simple-minded
							{
								ilg.Emit(OpCodes.Unbox, argType);
							}
							localSuccess.Generate(ilg);
						});
				}
			}
			ifSuccess.Generate(ilg);
		}
Пример #30
0
 public void CallVisitor(TextConst textConst)
 {
     result = new CGTextConst(textConst.value);
 }
Пример #31
0
		public CGLessThanOrEqual(CGExpr[] es) : base(es, leApplier) { }
Пример #32
0
 public void CallVisitor(Error error)
 {
     result = new CGError(error.value);
 }
Пример #33
0
		public CGStrictOperation(CGExpr[] es, Applier applier)
			: base(es) {
			this.applier = applier;
		}
Пример #34
0
 public void CallVisitor(NumberConst numbConst)
 {
     result = new CGNumberConst(numbConst.value);
 }
Пример #35
0
		public override CGExpr Residualize(CGExpr[] res) { return Make(res); }
Пример #36
0
		public CGLessThan(CGExpr[] es) : base(es, ltApplier) { }
Пример #37
0
		public CGEqual(CGExpr[] es) : base(es, eqApplier) { }
Пример #38
0
		/// <summary>
		/// Generates code to evaluate each expression es[sourceOffset,...] and  
		/// store it into array vs[0,...] on the stack top.
		/// Assumes an array vs of type Value[] is on the stack, and leaves array vs there.
		/// </summary>
		/// <param name="offset">The number of given argument expressions to ignore</param>
		/// <param name="es">The given (partial) argument expressions</param>
		internal static void CompileExpressionsAndStore(int sourceOffset, CGExpr[] es) {
			for (int i = sourceOffset; i < es.Length; i++) {
				ilg.Emit(OpCodes.Dup);
				ilg.Emit(OpCodes.Ldc_I4, i - sourceOffset);
				es[i].Compile();
				ilg.Emit(OpCodes.Stelem_Ref);
			}
		}
Пример #39
0
        public readonly bool negated;         // True if represents NOT(cachedExpr)

        public CachedAtom(CGExpr cond, List <CGCachedExpr> caches)
        {
            this.cachedExpr = new CGCachedExpr(cond, this, caches);
            this.negated    = false;
        }
Пример #40
0
		public abstract CGExpr Residualize(CGExpr[] res);
Пример #41
0
		public CGCachedExpr(CGExpr expr, CachedAtom cachedAtom, List<CGCachedExpr> caches) {
			this.expr = expr;
			this.cachedAtom = cachedAtom;
			this.cacheNumber = caches.Count;
			caches.Add(this);
		}
Пример #42
0
		public override CGExpr Residualize(CGExpr[] res) { return new CGNot(res); }
Пример #43
0
		public override CGExpr Residualize(CGExpr[] res) { return new CGLessThan(res); }
Пример #44
0
		public CGNot(CGExpr[] es) : base(es, notApplier) { }
Пример #45
0
		public CGGreaterThanOrEqual(CGExpr[] es) : base(es, geApplier) { }
Пример #46
0
        // Generate code to evaluate all argument expressions, including the receiver es[1]
        // if the method is an instance method, and convert their values to .NET types.

        private void CompileArgumentsAndApply(CGExpr[] es, Gen ifSuccess, Gen ifOther)
        {
            int argCount = es.Length - 1;

            // The error continuations must pop the arguments computed so far:
            Gen[] errorCont = new Gen[argCount];
            if (argCount > 0)
            {
                errorCont[0] = ifOther;
            }
            for (int i = 1; i < argCount; i++)
            {
                int ii = i;                 // Capture lvalue -- do NOT inline!
                errorCont[ii] = new Gen(delegate {
                    ilg.Emit(OpCodes.Pop);
                    errorCont[ii - 1].Generate(ilg);
                });
            }
            // Generate code, backwards, to evaluate argument expressions and
            // convert to external method's argument types
            for (int i = argCount - 1; i >= 0; i--)
            {
                // These local vars capture rvalue rather than lvalue -- do NOT inline them!
                CGExpr ei           = es[i + 1];
                Gen    localSuccess = ifSuccess;
                int    argIndex     = i;
                Type   argType      = ef.ArgType(i);
                Gen    ifError      = errorCont[i];
                // First some special cases to avoid boxing:
                if (argType == typeof(System.Double))
                {
                    ifSuccess = new Gen(
                        delegate {
                        ei.CompileToDoubleOrNan();
                        localSuccess.Generate(ilg);
                    });
                }
                else if (argType == typeof(System.Single))
                {
                    ifSuccess = new Gen(
                        delegate {
                        ei.CompileToDoubleOrNan();
                        ilg.Emit(OpCodes.Conv_R4);
                        localSuccess.Generate(ilg);
                    });
                }
                else if (signed32.Contains(argType))
                {
                    ifSuccess = new Gen(
                        delegate {
                        ei.CompileToDoubleProper(
                            new Gen(delegate {
                            ilg.Emit(OpCodes.Conv_I4);
                            localSuccess.Generate(ilg);
                        }),
                            ifError);
                    });
                }
                else if (unsigned32.Contains(argType))
                {
                    ifSuccess = new Gen(
                        delegate {
                        ei.CompileToDoubleProper(
                            new Gen(delegate {
                            ilg.Emit(OpCodes.Conv_U4);
                            localSuccess.Generate(ilg);
                        }),
                            ifError);
                    });
                }
                else if (argType == typeof(System.Int64))
                {
                    ifSuccess = new Gen(
                        delegate {
                        ei.CompileToDoubleProper(
                            new Gen(delegate {
                            ilg.Emit(OpCodes.Conv_I8);
                            localSuccess.Generate(ilg);
                        }),
                            ifError);
                    });
                }
                else if (argType == typeof(System.UInt64))
                {
                    ifSuccess = new Gen(
                        delegate {
                        ei.CompileToDoubleProper(
                            new Gen(delegate {
                            ilg.Emit(OpCodes.Conv_U8);
                            localSuccess.Generate(ilg);
                        }),
                            ifError);
                    });
                }
                else if (argType == typeof(System.Boolean))
                {
                    ifSuccess = new Gen(
                        delegate {
                        ei.CompileToDoubleProper(
                            new Gen(delegate {
                            ilg.Emit(OpCodes.Ldc_R8, 0.0);
                            ilg.Emit(OpCodes.Ceq);
                            localSuccess.Generate(ilg);
                        }),
                            ifError);
                    });
                }
                else if (argType == typeof(System.Char))
                {
                    ifSuccess = new Gen(
                        delegate {
                        ei.Compile();
                        ilg.Emit(OpCodes.Call, TextValue.toNakedCharMethod);
                        localSuccess.Generate(ilg);
                    });
                }
                else if (argType == typeof(System.String))
                {
                    ifSuccess = new Gen(
                        delegate {
                        ei.Compile();
                        UnwrapToString(localSuccess, ifError);
                    });
                }
                else                 // General cases: String[], double[], double[,], ...
                {
                    ifSuccess = new Gen(
                        delegate {
                        ei.Compile();
                        ilg.Emit(OpCodes.Call, ef.ArgConverter(argIndex).Method);
                        if (argType.IsValueType)                                 // must unbox wrapped value type, but this is too simple-minded
                        {
                            ilg.Emit(OpCodes.Unbox, argType);
                        }
                        localSuccess.Generate(ilg);
                    });
                }
            }
            ifSuccess.Generate(ilg);
        }
Пример #47
0
		public CGGreaterThan(CGExpr[] es) : base(es, gtApplier) { }
Пример #48
0
		public CGAnd(CGExpr[] es) : base(es) { }
Пример #49
0
		public CGIf(CGExpr[] es) : base(es) { }
Пример #50
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);
		}
Пример #51
0
		public CGOr(CGExpr[] es) : base(es) { }
Пример #52
0
		public override CGExpr Residualize(CGExpr[] res) { throw new ImpossibleException("CGSdfCall.Residualize"); }