private void CompileCallNoCallee( List <Instruction> instructions, RedwoodType[] argumentTypes, int[] argumentLocations, RedwoodType knownType) { if (knownType == null) { instructions.Add(new TryCallInstruction(argumentTypes, argumentLocations)); } else if (knownType.CSharpType == typeof(InternalLambda)) { instructions.Add(new InternalCallInstruction(argumentLocations)); } else if (knownType.CSharpType == typeof(ExternalLambda)) { instructions.Add(new ExternalCallInstruction(argumentLocations)); } else if (knownType.CSharpType == typeof(LambdaGroup)) { if (FullyResolved && knownType.GenericArguments != null) { RuntimeUtil.TrySelectOverload( argumentTypes, knownType.GenericArguments .Select(lambdaType => lambdaType .GenericArguments .SkipLast(1) .ToArray() ) .ToArray(), out int index ); instructions.Add(new LookupLambdaGroupOverloadInstruction(index)); instructions.Add(new ExternalCallInstruction(argumentLocations)); } else { instructions.Add(new TryCallInstruction(argumentTypes, argumentLocations)); } } else if (knownType.CSharpType == typeof(RedwoodType)) { instructions.Add(new LookupExternalMemberLambdaInstruction("Constructor", knownType)); instructions.Add(new ExternalCallInstruction(argumentLocations)); } else { throw new NotImplementedException(); } }
private void ResolveLambdaGroupOverload(RedwoodType[] argumentTypes) { if (LambdaType != null && LambdaType.CSharpType == typeof(LambdaGroup) && FullyResolved && (LambdaType.GenericArguments?.Length ?? 0) > 0) { RuntimeUtil.TrySelectOverload( argumentTypes, LambdaType .GenericArguments // Ignore the return type from lambdas .Select(overload => overload.GenericArguments.SkipLast(1).ToArray()) .ToArray(), out int index ); LambdaType = LambdaType.GenericArguments[index]; } }
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() )); } }
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; } } }