Ejemplo n.º 1
0
        public static bool CheckForRecursion(RCValue op,
                                             RCClosure previous,
                                             ref RCValue userop,
                                             ref RCArray <RCBlock> useropContext)
        {
            RCUserOperator name = op as RCUserOperator;

            if (name != null)
            {
                PreresolveUserOp(previous, op, ref userop, ref useropContext);
                RCClosure current = previous.Parent;
                while (current != null)
                {
                    RCUserOperator code = current.Code as RCUserOperator;
                    if (code != null)
                    {
                        if (userop == current.UserOp)
                        {
                            // Tail recursion detected
                            return(true);
                        }
                    }
                    current = current.Parent;
                }
            }
            // No tail recursion here
            return(false);
        }
Ejemplo n.º 2
0
        public static void PreresolveUserOp(RCClosure closure,
                                            RCValue op,
                                            ref RCValue resolved,
                                            ref RCArray <RCBlock> context)
        {
            // Now we just did the this context work so you know what that means.
            // We have to pass in this.
            RCUserOperator name = op as RCUserOperator;

            if (name == null)
            {
                return;
            }
            if (name._reference.Parts.Count > 1)
            {
                context = new RCArray <RCBlock> ();
            }
            resolved = Resolve(null, closure.Parent, name._reference.Parts, context);
        }
Ejemplo n.º 3
0
 public static bool DoIsLastCall(RCClosure closure,
                                 RCClosure arg,
                                 RCUserOperator op)
 {
     // Commenting these lines out breaks the case where the last
     // op is not really the last op. But why?
     if (arg != null)
     {
         bool result = arg.Code.IsLastCall(arg, null);
         if (result)
         {
             result = DoIsLastCall(closure, arg, (RCOperator)op);
         }
         return(result);
     }
     else
     {
         bool result = DoIsLastCall(closure, arg, (RCOperator)op);
         return(result);
     }
 }
Ejemplo n.º 4
0
        public RCOperator New(string op, RCValue left, RCValue right)
        {
            string     key    = op;
            RCOperator result = null;

            if (!_operator.ContainsKey(key))
            {
                result = new RCUserOperator(new RCReference(op));
                result.Init(op, left, right);
            }
            else
            {
                Type type = _operator[op];
                // This is a tiny optimization, avoids using reflection
                // if we are only going to call the base class RCOperator ctor.
                // But I would like to note that I am ok with New on operators being
                // slightly expensive because it will generally only happen during
                // parsing or macro expansion which are both expensive anyhow.
                if (type == typeof(RCOperator))
                {
                    result = new RCOperator();
                    result.Init(op, left, right);
                }
                else if (type.IsSubclassOf(typeof(RCOperator)))
                {
                    ConstructorInfo ctor = type.GetConstructor(_ctor);
                    if (ctor == null)
                    {
                        throw new Exception("No zero argument constructor found on type " + type);
                    }
                    result = (RCOperator)ctor.Invoke(null);
                    result.Init(op, left, right);
                }
            }
            return(result);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Start evaluation for a user-defined operator.
        /// </summary>
        public static void DoEvalUserOp(RCRunner runner, RCClosure closure, RCUserOperator op)
        {
            RCValue           code  = closure.UserOp;
            RCArray <RCBlock> @this = closure.UserOpContext;

            if (code == null)
            {
                if (op._reference.Parts.Count > 1)
                {
                    @this = new RCArray <RCBlock> ();
                }
                code = Resolve(op._reference._static, closure, op._reference.Parts, @this);
            }
            if (code == null)
            {
                throw new Exception("Cannot find definition for operator: " + op._reference.Name);
            }
            if (code.TypeCode == 's')
            {
                string  name  = ((RCString)code)[0];
                RCValue left  = closure.Result.Get("0");
                RCValue right = closure.Result.Get("1");
                if (left != null)
                {
                    RCSystem.Activator.Invoke(runner, closure, name, left, right);
                }
                else
                {
                    RCSystem.Activator.Invoke(runner, closure, name, right);
                }
            }
            else
            {
                code.Eval(runner, UserOpClosure(closure, code, @this, noClimb: false));
            }
        }
Ejemplo n.º 6
0
 public void EvalEval(RCRunner runner, RCClosure closure, RCBlock left, RCUserOperator right)
 {
     // Invocation using the activator requires a perfect match on the argument type.
     EvalEval(runner, closure, left, (RCOperator)right);
 }