Пример #1
0
 /// <summary>Add a new overload to the list</summary>
 internal void Add(ValueFunction function)
 {
     if (m_functions.AsArray.Count == 0)
     {	// first function decides if it's pre/in/postfix
         m_bConsumesPrevious = function.ConsumesPrevious;
         m_bConsumesNext = function.ConsumesNext;
         m_bRequiresBody = function.RequiresBody();
         // copy all metadata except parameters from single function to overload
         foreach (string key in function.Metadata.Raw.Keys)
             if (key != ValueFunction.keyPreviousPattern && key != ValueFunction.keyNextPattern)
                 WritableMetadata[key] = function.Metadata[key];
         AddFunction(function);
     }
     else
     {	// other functions must match fix
         if (m_bConsumesPrevious != function.ConsumesPrevious
             || m_bConsumesNext != function.ConsumesNext)
         {
             string expected = GetFix(m_bConsumesPrevious, m_bConsumesNext);
             string actual = GetFix(function.ConsumesPrevious, function.ConsumesNext);
             throw new Loki3Exception().AddWrongFix(expected, actual);
         }
         // other function must have same body requirement
         if (m_bRequiresBody != function.RequiresBody())
             throw new Loki3Exception().AddMissingBody(function);
         // copy all metadata from overload to new function
         foreach (string key in Metadata.Raw.Keys)
             function.WritableMetadata[key] = Metadata[key];
         AddFunction(function);
     }
 }
Пример #2
0
        internal BoundFunction(ValueFunction function, IScope scope)
        {
            m_function = function;
            m_scope = scope;

            foreach (string key in function.Metadata.Raw.Keys)
                WritableMetadata[key] = function.Metadata[key];
        }
Пример #3
0
        /// <summary>
        /// If function requires a body & it follows current line, add on body.
        /// 'requestor' will be advanced to the first line after the body.
        /// </summary>
        /// <returns>new function with body attached</returns>
        internal static Value DoAddBody(ValueFunction function, IScope scope, ILineRequestor requestor)
        {
            List<DelimiterList> body = DoGetBody(scope, requestor);
            // if no body to add to function, leave as-is
            if (body.Count == 0)
                return function;

            // we've built the entire body - now pass it to function
            Map map = new Map();
            map[ValueFunction.keyBody] = new ValueLine(body, scope);
            ValueFunctionPre functionPre = function as ValueFunctionPre;
            return functionPre.Eval(new ValueMap(map), new ScopeChain(scope));
        }
Пример #4
0
        /// <summary>
        /// Create a function that waits for the missing pre or post parameter,
        /// then bundles them all up and calls the first function
        /// </summary>
        /// <param name="nested">function to call once we get remaining parameters</param>
        /// <param name="passed">arguments that have already been passed</param>
        internal PartialFunctionIn(ValueFunction nested, DelimiterNode prev, DelimiterNode next)
        {
            m_nested = nested;
            m_prev = prev;
            m_next = next;

            // our pattern is the missing parameter; use same precedence as nested func
            Map meta = nested.Metadata;
            if (meta.ContainsKey(ValueFunctionOverload.keyIsOverload))
                WritableMetadata[ValueFunctionOverload.keyIsOverload] = new ValueBool(true);
            else if (m_prev != null)
                Init(null, meta[keyNextPattern], nested.Order);
            else
                Init(meta[keyPreviousPattern], null, nested.Order);
        }
Пример #5
0
 public void Exit()
 {
     if (m_onExitFunction != null)
     {
         ValueFunction func = m_onExitFunction;
         DelimiterNodeValue prev = (m_onExitPrevValue == ValueNil.Nil ? null : new DelimiterNodeValue(m_onExitPrevValue));
         DelimiterNodeValue next = (m_onExitNextValue == ValueNil.Nil ? null : new DelimiterNodeValue(m_onExitNextValue));
         m_onExitFunction = null;
         func.Eval(prev, next, this, this, null, null);
     }
 }
Пример #6
0
 public void AddOnExit(ValueFunction function, Value prevValue, Value nextValue)
 {
     m_onExitFunction = function;
     m_onExitPrevValue = prevValue;
     m_onExitNextValue = nextValue;
 }
Пример #7
0
 internal ValueFunctionOverload(ValueFunction function)
 {
     WritableMetadata[keyIsOverload] = new ValueBool(true);
     Add(function);
 }
Пример #8
0
        /// <summary>Figure out how specific overload is and add to sorted list</summary>
        private void AddFunction(ValueFunction function)
        {
            // calc the overload level of this function based on the params it expects,
            // store the level on the function
            int countParams = 0;
            int level = 0;
            if (function.ConsumesPrevious)
            {
                Value pattern = function.Metadata[ValueFunction.keyPreviousPattern];
                countParams += pattern.Count;
                level += CalcLevel(pattern);
            }
            if (function.ConsumesNext)
            {
                Value pattern = function.Metadata[ValueFunction.keyNextPattern];
                countParams += pattern.Count;
                level += CalcLevel(pattern);
            }
            level += PointsPerParam * countParams * (countParams - 1) / 2;
            function.WritableMetadata[keyOverloadLevel] = new ValueInt(level);

            // list is sorted from largest to smallest overload levels
            List<Value> list = m_functions.AsArray;
            int count = list.Count;
            bool bAdded = false;
            // todo: make this a binary search
            for (int i = 0; i < count; i++)
            {
                Value currentV = list[i];
                int currentLevel = currentV.Metadata[keyOverloadLevel].AsInt;
                if (level > currentLevel)
                {
                    list.Insert(i, function);
                    bAdded = true;
                    break;
                }
            }
            if (!bAdded)
                list.Add(function);
        }
Пример #9
0
            /// <summary>Evaluate this node, possibly consuming adjacent nodes</summary>
            internal void Eval(IScope scope, INodeRequestor nodes, ILineRequestor requestor)
            {
                if (m_state != NodeState.Node && m_state != NodeState.Function)
                    return;

                // get new value
                if (m_state == NodeState.Node)
                {	// hasn't been evaled at all
                    m_value = EvalNode.Do(m_node, scope, nodes, requestor);
                }
                else if (m_state == NodeState.Function)
                {	// previously resolved to a function
                    DelimiterNode previous = (m_func.ConsumesPrevious ? previous = nodes.GetPrevious() : null);
                    DelimiterNode next = (m_func.ConsumesNext ? next = nodes.GetNext() : null);
                    if ((m_func.ConsumesPrevious || m_func.ConsumesNext) && (previous == null && next == null))
                    {	// no prev/next parameters passed, perhaps it can use body?
                        if (m_func.RequiresBody() && requestor != null)
                        {	// tack on body if present
                            m_value = EvalList.DoAddBody(m_func, scope, requestor);
                        }
                        else
                        {	// function can't be evaled further
                            m_state = NodeState.Value;
                            return;
                        }
                    }
                    else
                    {
                        if (!m_func.ConsumesPrevious && !m_func.ConsumesNext && !m_func.RequiresBody() && !m_func.ForceEval)
                        {	// function can't be evaled further
                            m_state = NodeState.Value;
                            return;
                        }
                        m_value = m_func.Eval(previous, next, scope, scope, nodes, requestor);
                    }
                }

                if (m_value == null)
                {	// e.g. because node was a comment
                    m_state = NodeState.Empty;
                    return;
                }

                // store new info about this node
                m_node = new DelimiterNodeValue(m_value);
                m_order = (int)m_value.Order;
                if (m_value.Type == ValueType.Function)
                {
                    m_state = NodeState.Function;
                    m_func = m_value as ValueFunction;
                }
                else
                {
                    m_state = NodeState.Value;
                }
            }
Пример #10
0
            internal NodeEval(DelimiterNode node, IScope scope)
            {
                m_node = node;

                Token token = node.Token;
                if (token != null)
                {
                    Value value = scope.GetValue(token);
                    m_func = value as ValueFunction;
                    if (m_func != null)
                    {	// function
                        m_state = NodeState.Node;
                        m_order = (int)m_func.Order;
                    }
                    else if (value != null)
                    {	// variable
                        m_value = value;
                        m_state = NodeState.Value;
                    }
                    else
                    {	// built-in
                        try
                        {
                            m_value = EvalBuiltin.DoNoThrow(token);
                            if (m_value != null)
                                m_state = NodeState.Value;
                        }
                        catch (Exception) { }
                    }
                }
                else if (node.List != null)
                {
                    m_state = NodeState.Node;
                    m_order = (int)Order.Lowest;
                }
                else if (node.Value != null)
                {
                    m_value = node.Value;
                    m_order = (int)m_value.Order;
                    m_func = m_value as ValueFunction;
                    m_state = (m_func == null ? NodeState.Value : NodeState.Function);
                }
            }
Пример #11
0
 /// <summary>
 /// Delimited contents will be passed off to function to be evaluated
 /// </summary>
 /// <param name="function">function must take a next parameter of specified type</param>
 internal ValueDelimiter(string end, DelimiterType type, ValueFunction function)
 {
     Init(end, type, function);
 }
Пример #12
0
 private void Init(string end, DelimiterType type, ValueFunction function)
 {
     Map meta = WritableMetadata;
     meta[keyDelimEnd] = new ValueString(end);
     meta[keyDelimType] = new ValueInt((int)type);
     if (function != null)
         meta[keyDelimFunction] = function;
 }
Пример #13
0
 /// <summary>A function required a body but a body wasn't provided</summary>
 internal Loki3Exception AddMissingBody(ValueFunction function)
 {
     m_map[keyMissingBody] = function;
     return this;
 }