Esempio n. 1
0
        /// <inheritdoc />
        protected override EvaluationResult DoEval(Context context, ModuleLiteral env, EvaluationStackFrame frame)
        {
            var statisticHandler = InvocationStatisticHandler.Create(context);

            try
            {
                // If the functor is a named function, then we can skip closure creation and call the function directly.
                if (TryGetFunctionToInvoke(context, env, out var lambda, out var file))
                {
                    return(InvokeFunction(context, env, frame, lambda, frame, file, ref statisticHandler));
                }

                var evaluatedValue = Functor.Eval(context, env, frame);

                if (evaluatedValue.IsErrorValue)
                {
                    // Error should have been reported during the evaluation of the functor.
                    return(evaluatedValue);
                }

                // Note, need to check Functor type but not type of the evaluated value.
                if (evaluatedValue.IsUndefined && Functor is SelectorExpression selector)
                {
                    // Special case for unresolved selector to generate more specific error message.
                    return(HandleUnresolvedSelector(context, env, frame, selector));
                }

                if (evaluatedValue.Value is CallableValue callableValue)
                {
                    return(HandleCallableValue(context, env, frame, callableValue, ref statisticHandler));
                }

                if (evaluatedValue.Value is Closure closure)
                {
                    return(InvokeFunction(context, env, frame, closure.Function, closure.Frame, closure.Env, ref statisticHandler));
                }

                context.Errors.ReportUnexpectedValueType(
                    env,
                    Functor,
                    evaluatedValue,
                    typeof(CallableValue),
                    typeof(Closure));
            }
            catch (ConvertException convertException)
            {
                // ConversionException derives from EvaluationException but should be handled separatedly,
                context.Errors.ReportUnexpectedValueTypeOnConversion(env, convertException, Location);
            }
            catch (EvaluationException e)
            {
                e.ReportError(context.Errors, env, Location, expression: this, context: context);
            }
            catch (OperationCanceledException)
            {
                return(EvaluationResult.Canceled);
            }
            catch (Exception exception)
            {
                context.Errors.ReportUnexpectedAmbientException(env, exception, Location);

                // Getting here indicates a bug somewhere in the evaluator. Who knows what went wrong.
                // Let's re-throw and let some other global exception handler deal with it!
                throw;
            }
            finally
            {
                statisticHandler.TrackInvocation(context);
            }

            return(EvaluationResult.Error);
        }
Esempio n. 2
0
        private EvaluationResult EvaluateAmbientValueN(Context context, ModuleLiteral env, EvaluationStackFrame frame, CallableValue invocable, ref InvocationStatisticHandler statisticsHandler)
        {
            int numOfParams = invocable.CallableMember.MaxArity < short.MaxValue ? invocable.CallableMember.MaxArity : m_arguments.Length;

            // TODO: switch values to use EvaluationResult to avoid boxing.
            var values = new EvaluationResult[numOfParams];

            int i = 0;

            for (; i < invocable.CallableMember.MinArity; ++i)
            {
                values[i] = m_arguments[i].Eval(context, env, frame);

                if (values[i].IsErrorValue)
                {
                    return(EvaluationResult.Error);
                }
            }

            for (; i < numOfParams; ++i)
            {
                if (i >= m_arguments.Length)
                {
                    values[i] = EvaluationResult.Undefined;
                }
                else if (i < m_arguments.Length && i == numOfParams - 1 && invocable.CallableMember.Rest)
                {
                    values[i] = EvaluateRestArg(context, env, frame, i);
                }
                else
                {
                    values[i] = m_arguments[i].Eval(context, env, frame);
                }

                if (values[i].IsErrorValue)
                {
                    return(EvaluationResult.Error);
                }
            }

            statisticsHandler.CaptureStatistics(invocable.CallableMember.Statistic);

            return(invocable.Apply(context, values, frame));
        }
Esempio n. 3
0
        private EvaluationResult EvaluateAmbientValue2(Context context, ModuleLiteral env, EvaluationStackFrame frame, CallableValue invocable, ref InvocationStatisticHandler statisticsHandler)
        {
            if (m_arguments.Length == 0)
            {
                return(invocable.Apply(context, EvaluationResult.Undefined, EvaluationResult.Undefined, frame));
            }

            if (m_arguments.Length == 1)
            {
                var argValue = m_arguments[0].Eval(context, env, frame);
                return(argValue.IsErrorValue ? argValue : invocable.Apply(context, argValue, EvaluationResult.Undefined, frame));
            }

            var argValue0 = m_arguments[0].Eval(context, env, frame);

            if (argValue0.IsErrorValue)
            {
                return(argValue0);
            }

            var argValue1 = !invocable.CallableMember.Rest ? m_arguments[1].Eval(context, env, frame) : EvaluateRestArg(context, env, frame, 1);

            if (argValue1.IsErrorValue)
            {
                return(EvaluationResult.Error);
            }

            statisticsHandler.CaptureStatistics(invocable.CallableMember.Statistic);
            // TODO: change Apply to take EvaluationResult but not objects!
            return(invocable.Apply(context, argValue0, argValue1, frame));
        }
Esempio n. 4
0
        private EvaluationResult EvaluateAmbientValue1(Context context, ModuleLiteral env, EvaluationStackFrame frame, CallableValue invocable, ref InvocationStatisticHandler statisticsHandler)
        {
            if (m_arguments.Length == 0)
            {
                return(invocable.Apply(context, EvaluationResult.Undefined, frame));
            }

            var argValue = !invocable.CallableMember.Rest ? m_arguments[0].Eval(context, env, frame) : EvaluateRestArg(context, env, frame, 0);

            if (argValue.IsErrorValue)
            {
                return(argValue);
            }

            statisticsHandler.CaptureStatistics(invocable.CallableMember.Statistic);
            return(invocable.Apply(context, argValue, frame));
        }
Esempio n. 5
0
 private static EvaluationResult EvaluateAmbientValue0(Context context, EvaluationStackFrame frame, CallableValue invocable, ref InvocationStatisticHandler statisticsHandler)
 {
     statisticsHandler.CaptureStatistics(invocable.CallableMember.Statistic);
     return(invocable.Apply(context, frame));
 }
Esempio n. 6
0
        private EvaluationResult HandleCallableValue(Context context, ModuleLiteral currentEnv, EvaluationStackFrame frame, CallableValue invocable, ref InvocationStatisticHandler statisticsHandler)
        {
            // functor is a member function or property
            if (invocable.CallableMember.MinArity > m_arguments.Length)
            {
                context.Errors.ReportApplyAmbientNumberOfArgumentsLessThanMinArity(
                    currentEnv,
                    Functor,
                    invocable.CallableMember.MinArity,
                    m_arguments.Length,
                    Location);

                return(EvaluationResult.Error);
            }

            using (context.PrepareStackEntryForAmbient(this, currentEnv, frame))
            {
                if (context.IsStackOverflow)
                {
                    context.Errors.ReportStackOverflow(currentEnv, Location);
                    return(EvaluationResult.Error);
                }

                switch (invocable.CallableMember.MaxArity)
                {
                case 0:
                    return(EvaluateAmbientValue0(context, frame, invocable, ref statisticsHandler));

                case 1:
                    return(EvaluateAmbientValue1(context, currentEnv, frame, invocable, ref statisticsHandler));

                case 2:
                    return(EvaluateAmbientValue2(context, currentEnv, frame, invocable, ref statisticsHandler));

                default:
                    return(EvaluateAmbientValueN(context, currentEnv, frame, invocable, ref statisticsHandler));
                }
            }
        }