Example #1
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 #2
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 #3
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);
            }
        }