Example #1
0
        private void InferMethodGroup(MethodGroup mg, RelinqScriptExpression root, TypeInferenceCache cache)
        {
            // q: should existing but not accessible (security!) methods be included into the resolution?
            // a: yes and here's why:
            // scenario 1. Included; when overload resolution binds to an unauthorized method = crash.
            // scenario 2. Not included, so overload resolution binds to an unexpected method = fail.

            // lets us the fail fast if the resolution is unnecessary.
            // inferences made here won't be wasted anyways since they get cached
            var ctx = new TypeInferenceContext(root, cache, Integration);
            var preview = new TypeInferenceEngine(ctx);
            root.CallArgs().ForEach(child => preview.InferTypes(child));

            // we cannot pass the preview.Ctx inside since it might have
            // potentially half-inferred lambdas that won't be able to be reinferred
            // by MG resolution since ctx is init only.
            var resolved = mg.Resolve(ctx);

            cache.Add(root, resolved.Signature.ReturnType);
            cache.Invocations.Add(root, resolved);
            cache.Upgrade(resolved.Inferences);
        }
Example #2
0
        private void InferIndexer(IndexerExpression ie, TypeInferenceCache cache)
        {
            InferTypes(ie.Target, cache);
            var typeofTarget = cache[ie.Target];

            if (typeofTarget is ClrType)
            {
                var preview = cache.Clone();
                ie.Operands.ForEach(operand => InferTypes(operand, preview));
                var types = ie.Operands.Select(operand => preview[operand]);

                if (types.Any(type => type is Variant))
                {
                    cache.Add(ie, new Variant());
                    cache.Upgrade(preview);
                }
                else
                {
                    var alts = typeofTarget.LookupIndexers();
                    if (alts == null)
                    {
                        throw new NoSuchIndexerException(Root, ie, typeofTarget);
                    }

                    InferMethodGroup(alts, ie, cache);
                }
            }
            else if (typeofTarget is Variant)
            {
                cache.Add(ie, new Variant());
            }
            else
            {
                throw new NoSuchIndexerException(Root, ie, typeofTarget);
            }
        }
Example #3
0
        private void InferOperator(OperatorExpression oe, TypeInferenceCache cache)
        {
            var preview = cache.Clone();
            oe.Operands.ForEach(operand => InferTypes(operand, preview));
            var types = oe.Operands.Select(operand => preview[operand]);

            if (types.Any(type => type is Variant))
            {
                cache.Add(oe, new Variant());
                cache.Upgrade(preview);
            }
            else
            {
                var alts = oe.Type.LookupOperators(types.ToArray());

                // logical not can also be used to express ones complement
                // since they both correspond to a single LINQ expression type
                if (oe.Type == OperatorType.LogicalNot)
                {
                    var addendum = OperatorType.OnesComplement.LookupOperators(types.ToArray());
                    if (addendum != null)
                    {
                        var original = alts == null ? new MethodInfo[0] : alts.Alts;
                        alts = new MethodGroup(original.Concat(addendum.Alts), oe.Type.GetOpCode());
                    }
                }

                if (alts == null)
                {
                    throw new NoSuchOperatorException(Root, oe, types);
                }

                InferMethodGroup(alts, oe, cache);
            }
        }
Example #4
0
        private void InferInvoke(InvokeExpression ie, TypeInferenceCache cache)
        {
            InferTypes(ie.Target, cache);
            var typeofTarget = cache[ie.Target];

            if (typeofTarget is ClrType)
            {
                var preview = cache.Clone();
                ie.Args.ForEach(arg => InferTypes(arg, preview));
                var types = ie.Args.Select(arg => preview[arg]);

                if (types.Any(type => type is Variant))
                {
                    cache.Add(ie, new Variant());
                    cache.Upgrade(preview);
                }
                else
                {
                    var clrType = ((ClrType)typeofTarget).Type;
                    if (clrType.IsDelegate())
                    {
                        var sig = clrType.GetFunctionSignature();
                        InferMethodGroup(new MethodGroup(sig.AsArray(), clrType.Name), ie, cache);
                    }
                    else
                    {
                        throw new CannotBeInvokedException(Root, ie, typeofTarget);
                    }
                }
            }
            else if (typeofTarget is MethodGroup)
            {
                InferMethodGroup((MethodGroup)typeofTarget, ie, cache);
            }
            else if (typeofTarget is Variant)
            {
                cache.Add(ie, new Variant());
            }
            else
            {
                throw new CannotBeInvokedException(Root, ie, typeofTarget);
            }
        }