Example #1
0
        /// <summary>
        /// Evaluate line and body if needed.
        /// 'requestor' is positioned on the next line to eval.
        /// </summary>
        internal static Value DoOne(ILineRequestor requestor, IScope scope)
        {
            DelimiterList list = requestor.GetCurrentLine(scope);
            try
            {
                // eval using list's scope, falling back to passed in scope if not present
                IScope theScope = (list.Scope != null ? list.Scope : scope);
                Value value = EvalList.Do(list.Nodes, theScope, requestor);

                // if only item on line was a func, see if it needs a body
                ValueFunction func = value as ValueFunction;
                if (func != null && func.RequiresBody())
                    // if line created a partial function that needs a body,
                    // eval all subsequent indented lines
                    value = EvalList.DoAddBody(func, scope, requestor);

                // if only item was a map w/ one value, see if it needs a body
                if (func == null && value is ValueMap)
                {
                    Map map = value.AsMap;
                    if (map.Raw.Count == 1)
                    {
                        string key = "";
                        foreach (string k in map.Raw.Keys)
                            key = k;
                        func = map[key] as ValueFunction;
                        if (func != null && func.RequiresBody())
                            map[key] = EvalList.DoAddBody(func, scope, requestor);
                    }
                }

                // if only item was an array, see if last item needs a body
                if (func == null && value is ValueArray)
                {
                    List<Value> array = value.AsArray;
                    if (array.Count > 0)
                    {
                        func = array[array.Count - 1] as ValueFunction;
                        if (func != null && func.RequiresBody())
                            array[array.Count - 1] = EvalList.DoAddBody(func, scope, requestor);
                    }
                }

                requestor.Advance();

                return value;
            }
            catch (Loki3Exception e)
            {
                e.AddLine(list.ToString());
                throw e;
            }
        }
Example #2
0
        /// <summary>
        /// Get the body following the current line.
        /// 'requestor' will be positioned on the last line of the body.
        /// </summary>
        internal static List<DelimiterList> DoGetBody(IScope scope, ILineRequestor requestor)
        {
            List<DelimiterList> body = new List<DelimiterList>();

            // if we have a subset of all lines, we should simply use them as-is
            if (requestor.IsSubset())
            {
                while (requestor.HasCurrent())
                {
                    DelimiterList dline = requestor.GetCurrentLine(scope);
                    dline.Scope = scope;	// use this scope when evaling later
                    body.Add(dline);
                    requestor.Advance();
                }
                return body;
            }

            // else just grab indented lines
            DelimiterList pline = requestor.GetCurrentLine(scope);
            int parentIndent = pline.Indent;
            while (requestor.HasCurrent())
            {
                requestor.Advance();
                DelimiterList childLine = requestor.GetCurrentLine(scope);
                if (childLine == null || childLine.Indent <= parentIndent)
                {
                    requestor.Rewind();
                    break;	// now we have the body
                }
                childLine.Scope = scope;	// use this scope when evaling later

                // keep adding to the body
                body.Add(childLine);
            }
            return body;
        }