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); } }
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); } }
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); } }