Beispiel #1
0
        public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl)
        {
            CGExpr[] res = PEvalArgs(pEnv, hasDynamicControl);
            // The static argument positions are those that have args[i] != naError
            Value[] args = new Value[res.Length];
            bool    anyStatic = false, allStatic = true;

            for (int i = 0; i < res.Length; i++)
            {
                if (res[i] is CGConst)
                {
                    args[i]   = (res[i] as CGConst).Value;
                    anyStatic = true;
                }
                else
                {
                    args[i]   = ErrorValue.naError;                   // Generalize to dynamic
                    allStatic = false;
                }
            }
            if (!hasDynamicControl)
            {
                // This would be wrong, because the called function might contain
                // volatile functions and in that case should residualize:
                // if (allStatic)       // If all arguments static, just call the SDF
                //  return CGConst.Make(sdfInfo.Apply(args));
                // else
                if (anyStatic)                 // Specialize if there are static arguments
                {
                    return(Specialize(res, args));
                }
                // Do nothing if all arguments are dynamic
            }
            else
            {
                // If under dynamic control reduce to longest static prefix
                // where the argument values agree.
                // TODO: This is wrong -- should always specialize when the call is not
                // recursive
                ICollection <Value[]> pending = SdfManager.PendingSpecializations(sdfInfo.name);
                Value[] maxArray = null;
                int     maxCount = 0;
                foreach (Value[] vs in pending)
                {
                    int agree = AgreeCount(vs, args);
                    if (agree > maxCount)
                    {
                        maxCount = agree;
                        maxArray = vs;
                    }
                }
                if (maxCount > 0)
                {
                    SetNaInArgs(maxArray, args);
                    return(Specialize(res, args));
                }
            }
            return(new CGSdfCall(sdfInfo, res));
        }
Beispiel #2
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));
        }
Beispiel #3
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));
            }
        }
Beispiel #4
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));
                    }
                }
            }
        }