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); } }
public NoSuchOperatorException(RelinqScriptExpression root, OperatorExpression oe, IEnumerable<RelinqScriptType> operandTypes) : base(JSToCSharpExceptionType.NoSuchIndexer, root, oe) { InferredOperandTypes = operandTypes.ToArray(); OperatorName = oe.Type.GetOpCode(); }
private LinqExpression CompileOperator(OperatorExpression oe, CompilationContext ctx) { // not checking anything here. see comment in CompileConditional method's body // do not rely on oe.Type to detect the LINQ expression type, since // lookup/resolution might yield an operator with a different type // todo. validate this (LogicalNot -> OnesComplement, but not others) var sig = ctx.Invocations[oe].Signature; var sigTypes = sig.GetOperatorTypes(); var actualOpType = sigTypes.Count() > 1 ? oe.Type : sigTypes.Single(); if (!sig.IsRedirected()) { var compiledOperands = CompileCallArguments(ctx.Invocations[oe], oe.Operands, ctx); var ctorArgs = compiledOperands.Cast<Object>(); if (sig.IsUserDefinedOperator()) ctorArgs = ctorArgs.Concat(sig.AsArray()); return actualOpType.LinqExpressionFactory()(ctorArgs.ToArray()); } else { if (sig.IsLifted()) { // todo. implement this throw new NotImplementedException(String.Format( "Don't know how to compile the lifted operator: '{0}'", sig)); } else { var rebuiltSig = sig.RedirectionRoot(); var rebuiltCasts = ctx.Invocations[oe].Casts.Zip( sig.RedirectionRoot().ToXArgs(oe.XArgsCount()), (cast, param) => Cast.Lookup(cast.Source, param)); // todo. the stuff above sucks since there's no cast from string to object var compiledOperands = CompileCallArguments( rebuiltSig, rebuiltCasts, oe.Operands, ctx); var ctorArgs = compiledOperands.Cast<Object>(); ctorArgs = ctorArgs.Concat(rebuiltSig.AsArray()); return actualOpType.LinqExpressionFactory()(ctorArgs.ToArray()); } } }