internal override IEnumerable <NameExpression> Walk()
        {
            ReflectedOperatorName = RuntimeUtil.NameForOperator(Operator);
            TemporaryVariables    = new List <Variable>();
            if (ReflectedOperatorName == null)
            {
                switch (Operator)
                {
                case BinaryOperator.Assign:
                    if (Left is NameExpression ne)
                    {
                        ne.InLVal = true;
                    }
                    else
                    {
                        // Provide a temporary variable to hold the value of the
                        // assignment where it is needed.
                        TemporaryVariables.Add(new Variable
                        {
                            Temporary = true
                        });
                    }
                    break;

                case BinaryOperator.LogicalAnd:
                case BinaryOperator.LogicalOr:
                case BinaryOperator.As:
                    // No temporary variables needed
                    break;

                default:
                    throw new NotImplementedException();
                }
            }
            else
            {
                TemporaryVariables.Add(new Variable
                {
                    Temporary = true
                });
                TemporaryVariables.Add(new Variable
                {
                    Temporary = true
                });
            }

            List <NameExpression> freeVars = Left.Walk().ToList();

            freeVars.AddRange(Right.Walk());
            return(freeVars);
        }
예제 #2
0
        public int Execute(Frame frame)
        {
            RedwoodType leftType  = leftKnownType ?? RuntimeUtil.GetTypeOf(frame.stack[leftIndex]);
            RedwoodType rightType = rightKnownType ?? RuntimeUtil.GetTypeOf(frame.stack[rightIndex]);

            string lambdaName = RuntimeUtil.NameForOperator(op);
            Lambda leftLambda;
            Lambda rightLambda;

            leftLambda  = ResolveLambda(leftType, lambdaName);
            rightLambda = ResolveLambda(rightType, lambdaName);

            Lambda lambda = RuntimeUtil.CanonicalizeLambdas(leftLambda, rightLambda);

            lambda = RuntimeUtil.SelectSingleOverload(
                new RedwoodType[] { leftType, rightType },
                lambda
                );

            frame.result = lambda;
            return(1);

            Lambda ResolveLambda(RedwoodType type, string lambdaName)
            {
                Lambda lambda;

                if (type.CSharpType == null)
                {
                    int slot = type.staticSlotMap.GetValueOrDefault(lambdaName, -1);

                    if (slot == -1)
                    {
                        lambda = null;
                    }
                    else
                    {
                        lambda = type.staticLambdas[slot];
                    }
                }
                else
                {
                    MemberResolver.TryResolveLambda(null, type, lambdaName, out lambda);
                }

                return(lambda);
            }
        }
        private static RedwoodType ResolveBinaryOperator(
            BinaryOperator op,
            RedwoodType left,
            RedwoodType right,
            RedwoodType searchType,
            out Lambda lambda,
            out int?staticSlot,
            out int?index)
        {
            if (searchType.CSharpType == null)
            {
                staticSlot = searchType.staticSlotMap[RuntimeUtil.NameForOperator(op)];
                lambda     = null;

                RedwoodType overloadType = searchType.staticSlotTypes[staticSlot ?? -1];
                if (overloadType.CSharpType == typeof(LambdaGroup))
                {
                    if (!RuntimeUtil.TrySelectOverload(
                            new RedwoodType[] { left, right },
                            overloadType.GenericArguments
                            .Select(lambdaType => lambdaType
                                    .GenericArguments
                                    .SkipLast(1)
                                    .ToArray()
                                    )
                            .ToArray(),
                            out int resIndex
                            ))
                    {
                        index      = null;
                        staticSlot = null;
                        return(null);
                    }

                    index = resIndex;
                    return(overloadType.GenericArguments[resIndex]);
                }

                index = null;
                return(overloadType);
            }
            else
            {
                index      = null;
                staticSlot = null;
                if (!MemberResolver.TryResolveLambda(
                        searchType,
                        null,
                        RuntimeUtil.NameForOperator(op),
                        out Lambda lambdaOverloads))
                {
                    lambda = null;
                    return(null);
                }

                lambda = RuntimeUtil.SelectSingleOverload(
                    new RedwoodType[] { left, right },
                    lambdaOverloads
                    );

                return(RedwoodType.GetForLambdaArgsTypes(
                           typeof(ExternalLambda),
                           lambda.ReturnType,
                           lambda.ExpectedArgs.ToArray()
                           ));
            }
        }
예제 #4
0
        public async Task <FunctionDefinition> ParseOperatorDefinition()
        {
            if (!await MaybeToken("operator", true))
            {
                return(null);
            }

            TypeSyntax returnType;

            if (await MaybeToken("<", false))
            {
                returnType = await ParseType();

                if (!await MaybeToken(">", false))
                {
                    throw new NotImplementedException();
                }
            }
            else
            {
                returnType = null;
            }

            string operatorName = null;

            BinaryOperator?binaryOperator =
                await binaryOpParsers[0].ParseLoneOperatorSymbol(this);

            if (binaryOperator != null)
            {
                operatorName = RuntimeUtil.NameForOperator(binaryOperator.Value);
            }

            // TODO: Unary operators, implicit operator

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

            if (!await MaybeToken("(", false))
            {
                throw new NotImplementedException();
            }

            ParameterDefinition[] parameters;
            if (await MaybeToken(")", false))
            {
                parameters = new ParameterDefinition[0];
            }
            else
            {
                parameters = await ParseParameterList();

                if (parameters == null)
                {
                    throw new NotImplementedException();
                }
                if (!await MaybeToken(")", false))
                {
                    throw new NotImplementedException();
                }
            }

            BlockStatement functionCode = await ParseBlock();

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

            return(new FunctionDefinition
            {
                Name = operatorName,
                Parameters = parameters,
                Body = functionCode,
                ReturnType = returnType,
                Static = true
            });
        }