コード例 #1
0
        internal override void Bind(Binder binder)
        {
            binder.Bookmark();

            foreach (Variable variable in TemporaryVariables)
            {
                binder.BindVariable(variable);
            }

            Left.Bind(binder);
            Right.Bind(binder);

            binder.Checkout();

            RedwoodType leftType  = Left.GetKnownType();
            RedwoodType rightType = Right.GetKnownType();

            if (SpecialHandling(Operator) || leftType == null || rightType == null)
            {
                return;
            }
            else if (leftType.CSharpType != null && rightType.CSharpType != null)
            {
                // Resolve the static method
                MemberResolver.TryResolveOperator(
                    null,
                    null,
                    Left.GetKnownType(),
                    Right.GetKnownType(),
                    Operator,
                    out Lambda binaryOperationLambda);

                if (binaryOperationLambda == null)
                {
                    throw new NotImplementedException();
                }

                ResolvedOperator = binaryOperationLambda;
                LambdaType       = RedwoodType.GetForLambdaArgsTypes(
                    typeof(ExternalLambda),
                    binaryOperationLambda.ReturnType,
                    binaryOperationLambda.ExpectedArgs.ToArray()
                    );
            }
            else
            {
                RedwoodType[] lambdaTypes = new RedwoodType[2];
                Lambda[]      lambdas     = new Lambda[2];
                int?[]        slots       = new int?[2];
                int?[]        indexes     = new int?[2];

                // Search both the left and the right types for
                // static lambdas

                lambdaTypes[0] = ResolveBinaryOperator(
                    Operator,
                    leftType,
                    rightType,
                    leftType,
                    out lambdas[0],
                    out slots[0],
                    out indexes[0]
                    );

                lambdaTypes[1] = ResolveBinaryOperator(
                    Operator,
                    leftType,
                    rightType,
                    rightType,
                    out lambdas[1],
                    out slots[1],
                    out indexes[1]
                    );

                if (lambdaTypes[0] == null && lambdaTypes[1] == null)
                {
                    // There's no compatible operator between the two
                    throw new NotImplementedException();
                }
                else if (lambdaTypes[0] == null)
                {
                    LambdaType            = lambdaTypes[1];
                    ResolvedOperator      = lambdas[1];
                    ResolvedStaticSlot    = slots[1];
                    ResolvedOverloadIndex = indexes[1];
                    UsingLeftOperator     = false;
                }
                else if (lambdaTypes[1] == null)
                {
                    LambdaType            = lambdaTypes[0];
                    ResolvedOperator      = lambdas[0];
                    ResolvedStaticSlot    = slots[0];
                    ResolvedOverloadIndex = indexes[0];
                    UsingLeftOperator     = true;
                }
                else
                {
                    // TODO: This couldn't return null, could it?
                    RuntimeUtil.TrySelectOverload(
                        new RedwoodType[] { leftType, rightType },
                        lambdaTypes
                        .Select(lambdaType => lambdaType
                                .GenericArguments
                                .SkipLast(1)
                                .ToArray()
                                )
                        .ToArray(),
                        out int res
                        );

                    LambdaType            = lambdaTypes[res];
                    ResolvedOperator      = lambdas[res];
                    ResolvedStaticSlot    = slots[res];
                    ResolvedOverloadIndex = indexes[res];
                    UsingLeftOperator     = res == 0;
                }
            }
        }