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