Пример #1
0
 public static bool DoIsLastCall(RCClosure closure,
                                 RCClosure arg,
                                 RCBlock block)
 {
     // Costly call to GetName, will want to address this at some point.
     // return block.Evaluator.Return;
     return(block.GetName(closure.Index).Evaluator.Return);
 }
Пример #2
0
        public static RCBlock Append(RCBlock left, RCBlock right)
        {
            RCBlock result = left;

            for (int i = 0; i < right.Count; ++i)
            {
                RCBlock current = right.GetName(i);
                result = new RCBlock(result, current.Name, current.Evaluator, current.Value);
            }
            return(result);
        }
Пример #3
0
 public static void WriteBlock(RCArray <byte> result, RCBlock block)
 {
     // Pre-order traversal of the expression tree.
     result.Write((byte)'k');
     WriteScalarInt(result, block.Count);
     for (int i = 0; i < block.Count; ++i)
     {
         RCBlock name = block.GetName(i);
         Binary.WriteScalarString(name.Name, result);
         // Binary.WriteScalarString (RCEvaluator.For (name.Evaluator), result);
         Binary.WriteScalarString(name.Evaluator.Symbol, result);
         name.Value.ToByte(result);
     }
 }
Пример #4
0
        protected static RCBlock NextBlock(RCRunner runner,
                                           RCBlock block,
                                           RCClosure previous,
                                           RCValue val)
        {
            RCBlock code   = block.GetName(previous.Index);
            RCBlock result = new RCBlock(previous.Result,
                                         code.Name,
                                         code.Evaluator.Next,
                                         val);

            runner.Output(previous,
                          new RCSymbolScalar(null, code.Name),
                          val);
            return(result);
        }
Пример #5
0
        public RCValue RepAction(string action)
        {
            if (_state.Get(action) == null)
            {
                throw new ArgumentException(string.Format("Unknown action name: {0}", action));
            }
            RCValue result    = Rep(string.Format("{0} {{}}", action), restoreStateOnError: true);
            RCBlock variables = result as RCBlock;

            if (variables != null)
            {
                for (int i = 0; i < variables.Count; ++i)
                {
                    RCBlock variable = variables.GetName(i);
                    _state = new RCBlock(_state, variable.Name, variable.Evaluator, variable.Value);
                }
            }
            return(result);
        }
Пример #6
0
        protected void FinishTemplate(int escapeCount)
        {
            RCString     section;
            TemplateVars template = _templates.Peek();

            if (template._multilineTemplate)
            {
                for (int i = 0; i < _block.Count; ++i)
                {
                    RCBlock current = _block.GetName(i);
                    section = current.Value as RCString;
                    if (section != null && i % 2 == 0)
                    {
                        string content      = section[0];
                        int    spaces       = 0;
                        bool   broken       = false;
                        bool   hasLine      = false;
                        int    firstNewline = content.IndexOf('\n');
                        if (firstNewline > -1)
                        {
                            hasLine = true;
                        }
                        for (int j = firstNewline + 1; j < content.Length; ++j)
                        {
                            if (content[j] == ' ')
                            {
                                if (!broken)
                                {
                                    ++spaces;
                                }
                            }
                            else if (content[j] == '\n')
                            {
                                if (j > 0)
                                {
                                    template._minSpaces = Math.Min(template._minSpaces, spaces);
                                }
                                spaces  = 0;
                                broken  = false;
                                hasLine = true;
                            }
                            else
                            {
                                broken = true;
                            }
                        }
                        if (content.Length > 0 &&
                            content[content.Length - 1] != '\n' &&
                            hasLine &&
                            i < _block.Count - 1)
                        {
                            template._minSpaces = Math.Min(template._minSpaces, spaces);
                        }
                        if (template._minSpaces == int.MaxValue)
                        {
                            template._minSpaces = 0;
                        }
                    }
                }

                RCBlock final = RCBlock.Empty;
                // strip indentation (spaces only) from the lines in the content.
                // Ignore the first and last sections.
                for (int i = 0; i < _block.Count; ++i)
                {
                    RCBlock current = _block.GetName(i);
                    section = current.Value as RCString;
                    if (section != null && i % 2 == 0)
                    {
                        string        content = section[0];
                        StringBuilder builder = new StringBuilder();

                        int start = 0, end = 0;
                        // Skip past the initial newline in the first section.
                        if (i == 0)
                        {
                            while (content[start] != '\n')
                            {
                                ++start;
                            }
                            ++start;
                        }
                        else
                        {
                            while (end < content.Length)
                            {
                                if (content[end] == '\n')
                                {
                                    ++end;
                                    break;
                                }
                                ++end;
                            }
                            if (end < content.Length && end > 1 && content[end - 2] == '\r')
                            {
                                builder.Append(content.Substring(start, (end - 2) - start));
                                builder.Append("\n");
                            }
                            else
                            {
                                builder.Append(content.Substring(start, end - start));
                            }
                            start = end;
                        }
                        end = start;

GETLINE:
                        start = end + template._minSpaces;

                        while (end < content.Length)
                        {
                            if (content[end] == '\n')
                            {
                                ++end;
                                break;
                            }
                            ++end;
                        }

                        // The problem is when the first character is a newline this gets f****d up.
                        if (start < content.Length && end <= content.Length)
                        {
                            // string trimmed;
                            if (end < start)
                            {
                                builder.Append(content.Substring(0, end));
                            }
                            else
                            {
                                if (content.Length > 1 && content[end - 2] == '\r')
                                {
                                    builder.Append(content.Substring(start, (end - 2) - start));
                                    builder.Append("\n");
                                }
                                else
                                {
                                    builder.Append(content.Substring(start, end - start));
                                }
                            }
                            // builder.Append (trimmed);
                            goto GETLINE;
                        }
                        else
                        {
                            final = new RCBlock(final,
                                                current.Name,
                                                current.Evaluator,
                                                new RCString(builder.ToString()));
                        }
                    }
                    else
                    {
                        final = new RCBlock(final, current.Name, current.Evaluator, current.Value);
                    }
                }
                _result = new RCTemplate(final, escapeCount, true);
            }
            else
            {
                _result = new RCTemplate(_block, escapeCount, false);
            }

            // The template must either be all on one line,
            // or the first and last lines with the [? and ?] tokens
            // must be free of any other content.
            // So this loop needs to find out whether there are any newlines.
            // If there are then we also need to find out where the
            // first non-white character is.

            // Reset state for the possible next template.
            // _multilineTemplate = false;
            // _parsingContent = false;
            // _minSpaces = 0;
        }
Пример #7
0
 // Kicks off evaluation for a block.
 public static void DoEval(RCRunner runner, RCClosure closure, RCBlock block)
 {
     if (block.Count == 0)
     {
         DoYield(runner, closure, block);
     }
     else
     {
         RCBlock current = block.GetName(closure.Index);
         if (current.Evaluator.Invoke)
         {
             string op = ((RCString)current.Value)[0];
             RCSystem.Activator.Invoke(runner, closure, op, closure.Result);
         }
         else if (current.Evaluator.Template)
         {
             try
             {
                 RCString result = ExpandTemplate(new StringBuilder(),
                                                  (RCTemplate)current,
                                                  closure.Result,
                                                  0,
                                                  "");
                 runner.Yield(closure, result);
             }
             catch (Exception ex)
             {
                 RCException rcex = new RCException(closure,
                                                    ex,
                                                    RCErrors.Native,
                                                    "An exception was thrown by the template.");
                 runner.Finish(closure, rcex, (int)RCErrors.Native);
             }
         }
         else if (current.Evaluator.Pass)
         {
             DoYield(runner, closure, current.Value);
         }
         // This means that Value is an operator or a reference.
         else if (current.Value.ArgumentEval)
         {
             current.Value.Eval(runner,
                                new RCClosure(closure,
                                              closure.Bot,
                                              current.Value,
                                              closure.Left,
                                              closure.Result,
                                              0));
         }
         else if (current.Evaluator.Return)
         {
             DoYield(runner, closure, current.Value);
         }
         else
         {
             // I need something different to happen when we are at the top level already.
             // Or maybe I need to inject a wrapper closure when I do Rep this way?
             if ((closure.Index < block.Count - 1) || (closure.Parent != null))
             {
                 DoYield(runner, closure, current.Value);
             }
             else
             {
                 DoYield(runner, closure, current);
             }
         }
     }
 }
Пример #8
0
        // It is possible to have multiple concurrent observers.
        // However each value will only be returned to one of the observers.
        // It is hard to see a reason to create multiple observers but there
        // are multiple potential problems with implementing the constraint that there
        // be only one.
        public void Watch(RCClosure closure, long bot)
        {
            RCBlock result;

            lock (_botLock)
            {
                Queue <RCAsyncState> output = _output[bot];
                if (output.Count == 0)
                {
                    Queue <RCClosure> watchers;
                    if (!_watchers.TryGetValue(bot, out watchers))
                    {
                        watchers       = new Queue <RCClosure> ();
                        _watchers[bot] = watchers;
                    }
                    watchers.Enqueue(closure);
                    return;
                }
                RCBlock                  values = RCBlock.Empty;
                Stack <RCClosure>        parts  = new Stack <RCClosure> ();
                RCArray <RCSymbolScalar> names  = new RCArray <RCSymbolScalar> (output.Count);
                while (output.Count > 0)
                {
                    RCAsyncState   state  = output.Dequeue();
                    RCClosure      parent = state.Closure;
                    RCSymbolScalar name   = new RCSymbolScalar(null, parent.Fiber);
                    while (parent != null)
                    {
                        if (parent.Parent.Bot != parent.Bot ||
                            parent.Parent.Fiber != parent.Fiber)
                        {
                            break;
                        }
                        parts.Push(parent);
                        parent = parent.Parent;
                    }
                    while (parts.Count > 0)
                    {
                        RCClosure top = parts.Pop();
                        if (top.Code.IsBlock)
                        {
                            RCBlock code = (RCBlock)top.Code;
                            string  part = code.GetName(top.Index).Name;
                            if (part != "")
                            {
                                name = new RCSymbolScalar(name, part);
                            }
                            else
                            {
                                name = new RCSymbolScalar(name, (long)top.Index);
                            }
                        }
                    }
                    if (name != null)
                    {
                        RCValue val = (RCValue)state.Other;
                        values = new RCBlock(values, "", ":", val);
                        names.Write(name);
                    }
                }
                result = new RCBlock(null, "names", ":", new RCSymbol(names));
                result = new RCBlock(result, "values", ":", values);
            }
            Yield(closure, result);
        }
Пример #9
0
 public static void DoFormat(RCBlock block,
                             StringBuilder builder,
                             RCFormat args,
                             RCColmap
                             colmap,
                             int level)
 {
     if (block.Count == 0)
     {
         if (!args.Fragment)
         {
             builder.Append("{}");
         }
         return;
     }
     if (level > 0 || !args.Fragment)
     {
         builder.Append("{");
         builder.Append(args.Newline);
     }
     ++level;
     // Note the indexer requires a linear search backwards.
     // Maybe a custom iterator is in order?
     // It would also be useful for evaluation and other algorithms.
     for (int i = 0; i < block.Count; ++i)
     {
         RCBlock child = block.GetName(i);
         if (level > 1 || !args.Fragment)
         {
             for (int tab = args.Fragment ? 1 : 0; tab < level; ++tab)
             {
                 builder.Append(args.Indent);
             }
         }
         if (args.Syntax == "JSON")
         {
             builder.AppendFormat("\"{0}\"", child.RawName);
         }
         else if (child.EscapeName)
         {
             builder.Append(child.Name);
         }
         else
         {
             builder.Append(child.Name);
         }
         builder.Append(child.Evaluator.Symbol);
         if (child.Value != null)
         {
             child.Value.Format(builder, args, colmap, level);
         }
         else // Only the empty block has no value.
         {
             builder.Append("{}");
         }
         if (i < block.Count - 1)
         {
             builder.Append(args.RowDelimeter);
         }
     }
     builder.Append(args.Newline);
     --level;
     if (level > 0 || !args.Fragment)
     {
         for (int tab = args.Fragment ? 1 : 0; tab < level; ++tab)
         {
             builder.Append(args.Indent);
         }
         builder.Append("}");
     }
 }