Beispiel #1
0
 /// <nodoc />
 public Binding(StringId name, EvaluationResult body, LineInfo location)
     : this(name, body.Value, location)
 {
 }
Beispiel #2
0
 /// <inheritdoc />
 public override EvaluationResult Apply(Context context, T receiver, EvaluationResult arg1, EvaluationResult arg2, EvaluationStackFrame captures)
 {
     return(m_function(context, receiver, arg1, arg2, captures));
 }
Beispiel #3
0
 /// <inheritdoc />
 protected override EvaluationResult DoEval(Context context, ModuleLiteral env, EvaluationStackFrame frame)
 {
     return(EvaluationResult.Create(this));
 }
Beispiel #4
0
 /// <nodoc />
 public Binding(SymbolAtom name, EvaluationResult body, LineInfo location)
     : this(name.StringId, body.Value, location)
 {
     Contract.Requires(name.IsValid);
 }
Beispiel #5
0
        protected MergeFunction GetMergeFunction(Context context, EvaluationStackFrame captures, ObjectLiteral leftObject, EvaluationResult rightObject)
        {
            // If the left object has a custom merge, that trumps the other cases
            var customMergeLeft = leftObject.TryGetCustomMergeFunction(context, captures);

            if (customMergeLeft != null)
            {
                return(customMergeLeft);
            }

            // Otherwise if the right object has a custom merge, then use that one
            if (rightObject.Value is ObjectLiteral rightObjectLiteral)
            {
                var customMergeRight = rightObjectLiteral.TryGetCustomMergeFunction(context, captures);
                if (customMergeRight != null)
                {
                    return(customMergeRight);
                }
            }

            // Otherwise, use the default merge function
            return(GetDefaultMergeFunction(context, captures));
        }
Beispiel #6
0
        /// <summary>
        /// Helper method that returns a (object, object) -> object from a closure
        /// </summary>
        protected static MergeFunction GetCustomMergeFunctionFromClosure(Context context, EvaluationStackFrame captures, EvaluationResult customMergeClosure)
        {
            var closure     = Converter.ExpectClosure(customMergeClosure);
            int paramsCount = closure.Function.Params;

            return((leftObject, rightObject) =>
            {
                using (var frame = EvaluationStackFrame.Create(closure.Function, captures.Frame))
                {
                    frame.TrySetArguments(paramsCount, leftObject, rightObject);
                    return context.InvokeClosure(closure, frame);
                }
            });
        }
Beispiel #7
0
 /// <summary>
 /// Overrides this with <paramref name="right"/>.
 /// </summary>
 public virtual EvaluationResult Override(Context context, EvaluationResult right)
 {
     return(Combine(context, OverrideFunction, right));
 }
Beispiel #8
0
        /// <summary>
        /// Merges this with <paramref name="right"/>
        /// </summary>
        public virtual EvaluationResult Merge(Context context, EvaluationStackFrame captures, EvaluationResult right)
        {
            var mergeFunction = GetMergeFunction(context, captures, this, right);

            return(mergeFunction(EvaluationResult.Create(this), right));
        }
Beispiel #9
0
        /// <summary>
        /// Evaluates a right-hand side expression if not evaluated yet.
        /// </summary>
        protected internal static EvaluationResult EvalExpression(Context context, ModuleLiteral env, EvaluationResult o, EvaluationStackFrame args)
        {
            var e = o.Value as Expression;

            return(e?.Eval(context, env, args) ?? o);
        }
Beispiel #10
0
        /// <inheritdoc />
        public override bool TryProject(Context context, SymbolAtom name, ModuleLiteral origin, PredefinedTypes predefinedTypes, out EvaluationResult result, LineInfo location)
        {
            var value = this[name.StringId];

            if (value.IsUndefined)
            {
                // TODO: Optimize this for look-up miss cases (there can be tons of them).
                var resolvedMember = predefinedTypes.AmbientObject.ResolveMember(this, name) ?? (object)UndefinedValue.Instance;
                result = EvaluationResult.Create(resolvedMember);
            }
            else
            {
                result = value;
            }

            return(true);
        }
Beispiel #11
0
 /// <inheritdoc/>
 public override EvaluationResult Override(Context context, EvaluationResult right)
 {
     // Overriding an array always returns the right side
     return(right);
 }
Beispiel #12
0
        /// <inheritdoc />
        public override bool TryProject(Context context, SymbolAtom name, ModuleLiteral origin, PredefinedTypes predefinedTypes, out EvaluationResult result, LineInfo location)
        {
            if (name == context.Names.Length)
            {
                result = EvaluationResult.Create(Length);
                return(true);
            }

            var resolvedMember = predefinedTypes.AmbientArray.ResolveMember(this, name);

            if (resolvedMember == null)
            {
                // Array literals could not have arbitrary members.
                // So if the name was not resolved, reporting an error.
                // var locationForLogging = LocationForLogging(context, origin);
                var locationForLogging = UniversalLocation.FromLineInfo(location, origin.Path, context.PathTable);

                context.Logger.ReportMissingInstanceMember(
                    context.LoggingContext,
                    locationForLogging.AsLoggingLocation(),
                    name.ToDisplayString(context),
                    DisplayStringHelper.TypeToString(GetType(), context),
                    context.GetStackTraceAsString(locationForLogging));

                result = EvaluationResult.Error;
            }
            else
            {
                result = EvaluationResult.Create(resolvedMember);
            }

            return(true);
        }
Beispiel #13
0
        /// <summary>
        /// Combines this and right guided by 'combine' function. This is common logic for both merge and override
        /// </summary>
        internal EvaluationResult Combine(Context context, MergeFunction combine, EvaluationResult right)
        {
            // If the right hand side is undefined, short-circuit and return left.
            if (right.IsUndefined)
            {
                return(EvaluationResult.Create(this));
            }

            // If the right hand side is not an object literal (e.g. a number), then the combine just returns it. Same thing if it is an array.
            var rightObject = right.Value as ObjectLiteral;

            if (rightObject == null || rightObject is ArrayLiteral)
            {
                return(right);
            }

            // So at this point we know both sides are object literals, and therefore right members should be combined with left members

            // The result of a combine will have a number of members bounded by the summation between right and left members
            // So only when both sides are ObjectLiteralSlim we *could* end up with something that fits into an ObjectLiteralSlim
            // The following strategy puts all left side values into a dictionary first, to avoid the naive n^2 lookup algorithm
            // TODO: Still something better could be worked out when the result fits in an ObjectLiteralSlim (like sorting the keys first) so we avoid going to an intermediate dictionary
            var objectLiteralN = this as ObjectLiteralN;
            var values         = objectLiteralN != null?objectLiteralN.Values.ToDictionary() : Members.ToDictionary(kvp => kvp.Key.Value, kvp => kvp.Value);

            foreach (var binding in rightObject.Members)
            {
                // If the right member exists on the left, we replace it with whatever 'combine' gives us. Otherwise, we just reflect the right side on the left side.
                if (values.TryGetValue(binding.Key.Value, out var rightMember))
                {
                    values[binding.Key.Value] = combine(rightMember, binding.Value);
                }
                else
                {
                    values[binding.Key.Value] = binding.Value;
                }
            }

            var          entry = context.TopStack;
            LineInfo     location;
            AbsolutePath path;

            if (entry != null)
            {
                location = entry.InvocationLocation;
                path     = entry.Path;
            }
            else
            {
                location = default(LineInfo);
                path     = AbsolutePath.Invalid;
            }

            // We don't want to return an ObjectLiteralN unconditionally, to leverage ObjectLiteralSlim memory savings
            // If the result doesn't fit in an ObjectLiteralSlim, we already have a dictionary built for an ObjectLiteralN, so
            // we create it directly to avoid extra allocations
            if (values.Count > 5)
            {
                return(EvaluationResult.Create(new ObjectLiteralN(values, location, path)));
            }

            // Otherwise, we use the regular Create so it dispatches the creation to the right ObjectLiteralSlim
            return(EvaluationResult.Create(Create(values.SelectArray(kvp => new NamedValue(kvp.Key, kvp.Value)).ToList(), location, path)));
        }
Beispiel #14
0
 /// <inheritdoc />
 public sealed override bool TryProject(Context context, SymbolAtom name, ModuleLiteral origin, out EvaluationResult result, LineInfo location)
 {
     result = GetOrEvalField(context, name, recurs: false, origin: origin, location: Location);
     return(true);
 }
 /// <inheritdoc />
 public override EvaluationResult this[int index] => EvaluationResult.Create(m_data[index]);