public override RCValue Edit(RCRunner runner, RCValueDelegate editor) { RCOperator result = (RCOperator)base.Edit(runner, editor); if (result != null) { return(result); } RCValue left = null; if (_left != null) { left = _left.Edit(runner, editor); } RCValue right = _right.Edit(runner, editor); if (left != null || right != null) { if (left == null) { left = _left; } if (right == null) { right = _right; } result = runner.New(_name, left, right); return(result); } else { return(null); } }
public static void DoFormat(RCOperator op, StringBuilder builder, RCFormat args, RCColmap colmap, int level) { if (op.Left != null) { if (op.Left.IsOperator) { builder.Append("("); op.Left.Format(builder, args, colmap, level); builder.Append(")"); } else { op.Left.Format(builder, args, colmap, level); } builder.Append(" "); } op.BodyToString(builder, args, level); builder.Append(" "); // Note Right is not allowed to be null. op.Right.Format(builder, args, colmap, level); }
// Kicks off evaluation for an operator and its arguments. public static void DoEval(RCRunner runner, RCClosure closure, RCOperator op) { if (op.Left == null) { if (closure.Index == 0) { EvalArgument(runner, closure, op.Right); } else { op.EvalOperator(runner, closure); } } else { if (closure.Index == 0) { EvalArgument(runner, closure, op.Left); } else if (closure.Index == 1) { EvalArgument(runner, closure, op.Right); } else { op.EvalOperator(runner, closure); } } }
public static RCValue DoFinish(RCRunner runner, RCClosure closure, RCValue result) { while (closure != null) { RCBlock obj = closure.Code as RCBlock; if (obj != null) { if (obj.Count > 0 && obj.Evaluator.FinishBlock && result != closure.Code) { result = NextBlock(runner, obj, closure, result); } } RCOperator op = closure.Code as RCOperator; if (op != null) { result = op.Finish(result); } if (closure.Parent != null && (closure.Parent.Bot != closure.Bot || closure.Parent.Fiber != closure.Fiber)) { break; } closure = closure.Parent; } return(result); }
public void EvalEval(RCRunner runner, RCClosure closure, RCOperator right) { RCClosure parent = new RCClosure(closure.Parent, closure.Bot, right, closure.Left, RCBlock.Empty, 0); DoEval(runner, parent, right); }
public static RCException Overload(RCClosure closure, RCOperator op, RCValue left, RCValue right) { string message = string.Format(DYADIC_OVERLOAD_FORMAT, op.Name, left.TypeName, right.TypeName); return(new RCException(closure, RCErrors.Type, message)); }
public static bool DoIsLastCall(RCClosure closure, RCClosure arg, RCOperator op) { if (closure.Index == 1) { return(op.Left == null); } else { return(closure.Index == 2); } }
public static void WriteOperator(RCArray <byte> result, RCOperator op) { // Pre-order traversal of the expression tree. result.Write((byte)'o'); int count = op.Left == null ? 2 : 3; WriteScalarInt(result, count); if (op.Left != null) { op.Left.ToByte(result); } Binary.WriteScalarString(op.Name, result); op.Right.ToByte(result); }
protected static RCClosure OwnerOpOf(RCOperator op, RCClosure closure, out RCClosure child) { child = closure; RCClosure current = closure.Parent; while (current != null && !current.Code.ArgumentEval) { child = current; current = current.Parent; } return(current); }
protected static RCClosure NextParentOf(RCOperator op, RCClosure previous, out RCValue userop, out RCArray <RCBlock> useropContext) { // The only operator with IsHigherOrder set is switch. // Why is switch magical, why not each, take, fiber, etc... // Am I just missing tests for those? userop = null; useropContext = previous.UserOpContext; RCClosure argument0, argument1; bool recursion = false; if (previous.Parent == null) { return(previous.Parent); } recursion = CheckForRecursion(op, previous, ref userop, ref useropContext); if (!recursion) { return(previous.Parent); } RCClosure parent0 = OwnerOpOf(op, previous, out argument0); if (parent0 == null) { return(previous.Parent); } if (!parent0.Code.IsLastCall(parent0, argument0)) { if (!recursion) { return(previous.Parent); } } RCClosure parent1 = OwnerOpOf(op, parent0, out argument1); if (parent1 == null) { // parent1 is null when there is no switch in the last line. return(previous.Parent); } if (!parent1.Code.IsLastCall(parent1, argument1)) { return(previous.Parent); } return(parent1.Parent); }
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); }
public static bool DoIsBeforeLastCall(RCClosure closure, RCOperator op) { return(false); // We now check explicitly for the tail recursive case // This means less need to worry about "last call" status // RCUserOperator is the only place where this operation might return true now. // There is never a need to eliminate the tail stack frame in the case of a // built-in. // Still I don't feel quite ready to excise all of this "last call" code. // We will save that until the production system is ready. // So that we can do a full and proper regression. // It's possible there is something I'm missing. /* * if (closure.Index == 0) * { * return op.Left == null; * } * else * { * return closure.Index == 1; * } */ }
public static void DoEvalOperator(RCRunner runner, RCClosure closure, RCOperator op) { RCValue left = closure.Result.Get("0"); RCValue right = closure.Result.Get("1"); RCValue virtop = Resolve(null, closure, new RCArray <string> (op.Name), null, true); if (virtop != null) { RCClosure parent = UserOpClosure(closure, virtop, null, noClimb: false); virtop.Eval(runner, parent); return; } if (left == null) { RCSystem.Activator.Invoke(runner, closure, op.Name, right); } else { RCSystem.Activator.Invoke(runner, closure, op.Name, left, right); } // A lot of good men died to bring us this one line of code... // Let's keep this around as a memorial. // right.BindRight (runner, closure, this, left); }
public void ToString(StringBuilder builder, int indent, bool firstOnTop) { RCClosure closure = this; Stack <string> lines = new Stack <string> (); // Do not include the global namespace in the stack trace. while (closure != null && closure.Parent != null) { if (closure.Code != null) { RCOperator op = closure.Code as RCOperator; if (op != null) { lines.Push(string.Format("-- {0}", op.ToString())); } } RCBlock result = closure.Result; while (result != null) { if (result.Value != null) { RCCube acube = result.Value as RCCube; if (acube != null) { string value = acube.FlatPack().Format(RCFormat.Default); lines.Push(value); } else { string value = result.Value.Format(RCFormat.Default); value = string.Format("{0}:{1}", result.Name, value); value = value.Substring(0, Math.Min(80, value.Length)); lines.Push(value); } } result = result.Previous; } closure = closure.Parent; } if (firstOnTop) { builder.AppendFormat("--- BEGIN STACK (bot:{0},fiber:{1},lines:{2}) ---\n", closure.Bot, closure.Fiber, lines.Count); while (lines.Count > 0) { builder.AppendLine(lines.Pop()); } builder.AppendFormat("--- END STACK ---\n"); } else { builder.AppendFormat("--- END STACK (bot:{0},fiber:{1},lines:{2}) ---\n", closure.Bot, closure.Fiber, lines.Count); string[] linesInOrder = lines.ToArray(); for (int i = linesInOrder.Length - 1; i >= 0; --i) { builder.AppendLine(linesInOrder[i]); } builder.AppendFormat("--- BEGIN STACK ---\n"); } }
// Construct the next closure for an operator. public static RCClosure DoNext(RCOperator op, RCRunner runner, RCClosure head, RCClosure previous, RCValue result) { if (op.Left == null) { if (previous.Index == 0) { RCValue userop; RCArray <RCBlock> useropContext; RCClosure nextParentOf = NextParentOf(op, previous, out userop, out useropContext); RCClosure next = new RCClosure(nextParentOf, head.Bot, op, previous.Left, new RCBlock(null, "1", ":", result), previous.Index + 1, userop, useropContext); return(next); } else if (previous.Index == 1 && previous.Parent != null) { return(previous.Parent.Code.Next(runner, head == null ? previous : head, previous.Parent, result)); } else { return(null); } } else { if (previous.Index == 0) { return(new RCClosure(previous.Parent, head.Bot, op, result, previous.Result, previous.Index + 1, previous.UserOp, previous.UserOpContext)); } else if (previous.Index == 1) { RCValue userop; RCArray <RCBlock> useropContext; RCClosure next = new RCClosure(NextParentOf(op, previous, out userop, out useropContext), head.Bot, op, // reset "pocket" left to null. null, // fold it into the current context for the // final eval. new RCBlock(new RCBlock(null, "0", ":", previous.Left), "1", ":", result), previous.Index + 1, userop, useropContext); return(next); } else if (previous.Index == 2 && previous.Parent != null) { return(previous.Parent.Code.Next(runner, head == null ? previous : head, previous.Parent, result)); } else if (previous.Parent != null && previous.Parent.Parent != null) { return(previous.Parent.Parent.Code.Next(runner, head == null ? previous : head, previous.Parent.Parent, result)); } else { return(null); } } }
public void EvalEval(RCRunner runner, RCClosure closure, RCBlock left, RCOperator right) { RCClosure parent = UserOpClosure(closure, right, new RCArray <RCBlock> (left), noClimb: true); DoEval(runner, parent, right); }
public void EvalApply(RCRunner runner, RCClosure closure, RCOperator left, object right) { RCClosure parent = UserOpClosure(closure, left, null, null, (RCValue)right); DoEval(runner, parent, left); }