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); }
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); }
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); } }
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); }
/// <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)); } }
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); }