bool HasMostDerivedArgs(OverloadResult other) { bool preferthis = false; for (int i = 0; i < Parameters.Parameters.Length; i++) { var pt = Binder.FindType(Parameters.Parameters[i].ParameterType); var po = Binder.FindType(other.Parameters.Parameters[i].ParameterType); if (pt.IsSubclassOf(po)) { return(true); } // when the rest of the arguments do not make a difference // then prefer Int32 over UInt32 if (pt == Compilation.Get(WellKnownTypes.System_Int32) && po == Compilation.Get(WellKnownTypes.System_UInt32)) { preferthis = true; } // when no preference then choose the one with a usual argument // over the one without usual. else if (pt == Compilation.Get(WellKnownTypes.XSharp___Usual) && po != Compilation.Get(WellKnownTypes.XSharp___Usual) && !preferthis) { preferthis = true; } } return(preferthis); }
internal OverloadResult AskUserForCorrectOverload(IList <OverloadResult> matching, ArgList args) { OverloadResult res = null; if (Options.Resolver != null) { res = matching[0]; var argtypes = new System.Type[args.Args.Count]; for (int i = 0; i < args.Args.Count; i++) { argtypes[i] = args.Args[i].Expr.Datatype.Type; } Symbol lhs = matching[0].Symbol; int result = 0; for (int i = 1; i < matching.Count && res != null; i++) { var rhs = matching[i].Symbol; MemberInfo m1 = null, m2 = null; if (lhs is ConstructorSymbol) { var c1 = lhs as ConstructorSymbol; var c2 = rhs as ConstructorSymbol; m1 = c1.MethodBase; m2 = c2.MethodBase; } if (lhs is MethodSymbol) { var ms1 = lhs as MethodSymbol; var ms2 = rhs as MethodSymbol; m1 = ms1.MethodBase; m2 = ms2.MethodBase; } if (lhs is PropertySymbol) { var p1 = lhs as PropertySymbol; var p2 = rhs as PropertySymbol; m1 = p1.Property; m2 = p2.Property; } result = this.Options.Resolver(m1, m2, argtypes); switch (result) { case 1: break; case 2: lhs = rhs; res = matching[i]; break; case 0: res = null; break; } } } return(res); }
static void CheckArguments(MemberSymbol symbol, ParameterListSymbol paramList, ArgList args, ref OverloadResult ovRes, BindOptions options) { var parameters = paramList.Parameters; var nParams = parameters.Length; var fixedArgs = args.Args.Count; var varArgs = 0; var missingArgs = 0; bool hasExtraArgs = false; if (nParams <= fixedArgs) { if (paramList.HasParamArray) { varArgs = fixedArgs - (nParams - 1); fixedArgs = nParams - 1; } else if (nParams < fixedArgs) { hasExtraArgs = true; } } else if (nParams > fixedArgs) { if (paramList.HasParamArray) { missingArgs = nParams - fixedArgs - 1; } else { missingArgs = nParams - fixedArgs; } } if (!hasExtraArgs) { var ovr = OverloadResult.Create(symbol, paramList, fixedArgs, varArgs, missingArgs); for (int p = 0; p < fixedArgs; p++) { ovr.ArgConversion(p, ArgumentConversion(args.Args[p], parameters[p], options)); } if (missingArgs > 0) { for (int p = fixedArgs; p < fixedArgs + missingArgs; p++) { ovr.ArgConversion(p, ArgumentConversion(null, parameters[p], options)); } } else if (paramList.HasParamArray) { var varArgType = FindType(parameters[fixedArgs].ParameterType.GetElementType()); for (int p = fixedArgs; p < fixedArgs + varArgs; p++) { ovr.ArgConversion(p, VarArgumentConversion(args.Args[p], varArgType, options)); } } ovRes = ovr.Better(ovRes); } }
internal MemberSymbol BindMethodCall(Expr expr, Symbol symbol, ArgList args, out Expr self) { OverloadResult ovRes = null; var res = TryBindCall(expr, symbol, args, out self, ref ovRes, Options.Binding); if (res != null) { return(res); } throw MethodCallBindError(expr, symbol, args, ovRes); }
internal MemberSymbol BindArrayAccess(Expr self, Symbol symbol, ArgList args) { OverloadResult ovRes = null; var res = TryBindArrayAccess(self, symbol, args, ref ovRes, Options.Binding); if (res != null) { return(res); } throw ArrayAccessBindError(self, symbol, args, ovRes); }
bool HasMostDerivedArgs(OverloadResult other) { for (int i = 0; i < Parameters.Parameters.Length; i++) { var pt = Binder.FindType(Parameters.Parameters[i].ParameterType); var po = Binder.FindType(other.Parameters.Parameters[i].ParameterType); if (pt.IsSubclassOf(po)) { return(true); } } return(false); }
static void ApplyConversions(ArgList args, OverloadResult ovRes) { var parameters = ovRes.Parameters.Parameters; for (int i = 0; i < ovRes.FixedArgs; i++) { var conv = ovRes.Conversions[i]; if (conv.Kind != ConversionKind.Identity) { Convert(ref args.Args[i].Expr, FindType(parameters[i].ParameterType), conv); } if (conv is ConversionSymbolToConstant) { Convert(ref args.Args[i].Expr, FindType(parameters[i].ParameterType), BindOptions.Default); } } if (ovRes.MissingArgs > 0) { for (int i = ovRes.FixedArgs; i < ovRes.FixedArgs + ovRes.MissingArgs; i++) { var conv = ovRes.Conversions[i]; var a = new Arg(LiteralExpr.Bound(((ConversionSymbolToConstant)conv).Constant)); Convert(ref a.Expr, FindType(parameters[i].ParameterType), BindOptions.Default); args.Args.Add(a); } } else if (ovRes.Parameters.HasParamArray) { var varArgs = new List <Expr>(ovRes.VarArgs); var varArgType = FindType(parameters[ovRes.FixedArgs].ParameterType.GetElementType()); for (int i = ovRes.FixedArgs; i < ovRes.FixedArgs + ovRes.VarArgs; i++) { var conv = ovRes.Conversions[i]; Convert(ref args.Args[i].Expr, varArgType, conv); varArgs.Add(args.Args[i].Expr); } while (args.Args.Count > ovRes.FixedArgs) { args.Args.RemoveAt(args.Args.Count - 1); } args.Args.Add(new Arg(LiteralArray.Bound(varArgs, varArgType))); } }
internal Symbol BindCtorCall(Expr expr, Symbol symbol, ArgList args) { if ((symbol as TypeSymbol).IsValueType && args.Args.Count == 0) { return(new ObjectInitializerSymbol(symbol as TypeSymbol)); } Expr dummySelf; OverloadResult ovRes = null; var res = TryBindCall(null, symbol.Lookup(SystemNames.CtorName), args, out dummySelf, ref ovRes, Options.Binding); if (res != null) { return(res); } throw CtorCallBindError(expr, symbol, args, ovRes); }
internal static CompilationError CtorCallBindError(Expr expr, Symbol symbol, ArgList args, OverloadResult ovRes) { if (ovRes?.Valid != true) { if (symbol is SymbolList) { return(expr.Error(ErrorCode.NoSuitableCtor)); } else if (symbol is ConstructorSymbol) { return(expr.Error(ErrorCode.ArgumentsNotMatchCtor)); } else { return(expr.Error(ErrorCode.CtorNotFound)); } } if (ovRes.Unique == false) { return(expr.Error(ErrorCode.AmbiguousCall)); } return(expr.Error(ErrorCode.CtorNotFound)); }
internal static CompilationError MethodCallBindError(Expr expr, Symbol symbol, ArgList args, OverloadResult ovRes) { if (ovRes?.Valid != true) { var self = (expr as MemberAccessExpr)?.Expr; bool isStatic = self == null; if (symbol is SymbolList) { bool hasMethod = (symbol as SymbolList).SymbolTypes.HasFlag(MemberTypes.Method) || (symbol as SymbolList).SymbolTypes.HasFlag(MemberTypes.Constructor); bool validStatic = false; foreach (var s in (symbol as SymbolList).Symbols) { if ((s as MethodSymbol)?.Method.IsStatic == isStatic || symbol is ConstructorSymbol) { validStatic = true; } } if (validStatic) { return(expr.Error(ErrorCode.NoSuitableOverload, symbol.MemberName())); } else if (isStatic) { return(expr.Error(ErrorCode.NoStaticOverload, symbol.MemberName())); } else { return(expr.Error(ErrorCode.NoInstanceOverload, symbol.MemberName())); } } else if (symbol is MethodSymbol) { if ((symbol as MethodSymbol)?.Method.IsStatic == isStatic || symbol is ConstructorSymbol) { return(expr.Error(ErrorCode.ArgumentsNotMatch, symbol.MemberName())); } else if (isStatic) { return(expr.Error(ErrorCode.NoStaticMethod, symbol.MemberName())); } else { return(expr.Error(ErrorCode.NoInstanceMethod, symbol.MemberName())); } } else if (symbol is MemberSymbol) { return(expr.Error(ErrorCode.MemberNotMethod, symbol.MemberName())); } else if (expr.Symbol != null) { return(expr.Error(ErrorCode.NotAMethod, symbol)); } else if (expr is QualifiedNameExpr) { return(expr.Error(ErrorCode.MemberNotFound, (expr as QualifiedNameExpr).Name)); } else if (expr is MemberAccessExpr exprAccess) { if (exprAccess.Member is NameExpr memberName) { return(expr.Error(ErrorCode.MemberNotFound, memberName.Name)); } else { return(expr.Error(ErrorCode.NameExpected)); } } } if (ovRes?.Unique == false) { return(expr.Error(ErrorCode.AmbiguousCall)); } return(expr.Error(ErrorCode.NotFound, "Expression")); }
internal static CompilationError ArrayAccessBindError(Expr self, Symbol symbol, ArgList args, OverloadResult ovRes) { return(self.Error(ErrorCode.IndexerNotFound, self)); }
internal OverloadResult Better(OverloadResult other) { if (other?.Valid == true) { if (!Valid) { return(other); } else if (other.TotalCost < TotalCost) { return(other); } else if (other.TotalCost > TotalCost) { return(this); } else if (other.VarArgs < VarArgs) { return(other); } else if (other.VarArgs > VarArgs) { return(this); } else if (other.MissingArgs < MissingArgs) { return(other); } else if (other.MissingArgs > MissingArgs) { return(this); } else if (other.Parameters.Parameters.Length < Parameters.Parameters.Length) { return(other); } else if (other.Parameters.Parameters.Length > Parameters.Parameters.Length) { return(this); } else if (other.HasMostDerivedArgs(this)) { return(other); } else if (HasMostDerivedArgs(other)) { return(this); } else if (Symbol.DeclaringType.IsSubclassOf(other.Symbol.DeclaringType)) { return(this); } else if (other.Symbol.DeclaringType.IsSubclassOf(Symbol.DeclaringType)) { return(other); } else { Equivalent = other; ExtraValid += other.ExtraValid + 1; } } return(this); }
internal static CompilationError MethodCallBindError(Expr expr, Symbol symbol, ArgList args, OverloadResult ovRes) { if (ovRes?.Valid != true) { var self = (expr as MemberAccessExpr)?.Expr; bool isStatic = self == null; if (symbol is SymbolList sl) { bool validStatic = false; foreach (var s in sl.Symbols) { if (s is MethodSymbol ms && ms.Method.IsStatic == isStatic) { validStatic = true; } if (symbol is ConstructorSymbol cs && cs.Constructor.IsStatic == isStatic) { validStatic = true; } } if (validStatic) { return(expr.Error(ErrorCode.NoSuitableOverload, symbol.MemberName())); } else if (isStatic) { return(expr.Error(ErrorCode.NoStaticOverload, symbol.MemberName())); } else { return(expr.Error(ErrorCode.NoInstanceOverload, symbol.MemberName())); } } else if (symbol is MethodSymbol || symbol is ConstructorSymbol) { if ((symbol as MethodSymbol)?.Method.IsStatic == isStatic) { return(expr.Error(ErrorCode.ArgumentsNotMatch, symbol.MemberName())); } else if ((symbol as ConstructorSymbol)?.Constructor.IsStatic == isStatic) { return(expr.Error(ErrorCode.ArgumentsNotMatch, symbol.MemberName())); } else if (isStatic) { return(expr.Error(ErrorCode.NoStaticMethod, symbol.MemberName())); } else { return(expr.Error(ErrorCode.NoInstanceMethod, symbol.MemberName())); } } else if (symbol is MemberSymbol) { return(expr.Error(ErrorCode.MemberNotMethod, symbol.MemberName())); } else if (expr.Symbol != null) { return(expr.Error(ErrorCode.NotAMethod, symbol)); } else if (expr is QualifiedNameExpr) { return(expr.Error(ErrorCode.MemberNotFound, (expr as QualifiedNameExpr).Name)); } else if (expr is MemberAccessExpr exprAccess) { if (exprAccess.Member is NameExpr memberName) { return(expr.Error(ErrorCode.MemberNotFound, memberName.Name)); } else { return(expr.Error(ErrorCode.NameExpected)); } } } if (ovRes?.Unique == false) { string sMessage1 = ""; string sMessage2 = ""; if (ovRes?.Symbol is MethodSymbol msym) { sMessage1 = msym.Signature; } if (ovRes?.Equivalent?.Symbol is MethodSymbol msym2) { sMessage2 = msym2.Signature; } return(expr.Error(ErrorCode.AmbiguousCall, sMessage1, sMessage2)); } return(expr.Error(ErrorCode.NotFound, "Expression", "")); }
internal MemberSymbol TryBindArrayAccess(Expr self, Symbol symbol, ArgList args, ref OverloadResult ovRes, BindOptions options) { bool isStatic = self == null; var matching = new List <OverloadResult>(); if ((symbol as PropertySymbol)?.IsStatic == isStatic) { CheckArguments(symbol as PropertySymbol, (symbol as PropertySymbol).Parameters, args, ref ovRes, options); } else if ((symbol as SymbolList)?.HasProperty == true) { var properties = symbol as SymbolList; for (int i = 0; i < properties.Symbols.Count; i++) { var p = properties.Symbols[i]; if ((p as PropertySymbol)?.IsStatic == isStatic) { CheckArguments(p as PropertySymbol, (p as PropertySymbol).Parameters, args, ref ovRes, options); if (ovRes?.Exact == true) { break; } if (ovRes != null) { if (!matching.Contains(ovRes)) { matching.Add(ovRes); } if (ovRes.Equivalent != null && !matching.Contains(ovRes.Equivalent)) { matching.Add(ovRes.Equivalent); } } } } } Expr writeBack; if (ovRes?.Unique == true) { ApplyConversions(args, ovRes, out writeBack); return(ovRes.Symbol); } if (matching.Count > 1 && ovRes.Valid && Options.Resolver != null) { var res = AskUserForCorrectOverload(matching, args); if (res != null) { ovRes = res; ApplyConversions(args, ovRes, out writeBack); return(ovRes.Symbol); } } return(null); }
internal static MemberSymbol TryBindArrayAccess(Expr self, Symbol symbol, ArgList args, ref OverloadResult ovRes, BindOptions options) { bool isStatic = self == null; if ((symbol as PropertySymbol)?.IsStatic == isStatic) { CheckArguments(symbol as PropertySymbol, (symbol as PropertySymbol).Parameters, args, ref ovRes, options); } else if ((symbol as SymbolList)?.HasProperty == true) { var properties = symbol as SymbolList; for (int i = 0; i < properties.Symbols.Count; i++) { var p = properties.Symbols[i]; if ((p as PropertySymbol)?.IsStatic == isStatic) { CheckArguments(p as PropertySymbol, (p as PropertySymbol).Parameters, args, ref ovRes, options); if (ovRes?.Exact == true) { break; } } } } if (ovRes?.Unique == true) { ApplyConversions(args, ovRes); return(ovRes.Symbol); } return(null); }
internal static MemberSymbol TryBindCall(Expr expr, Symbol symbol, ArgList args, out Expr self, ref OverloadResult ovRes, BindOptions options) { self = (expr as MemberAccessExpr)?.Expr; bool isStatic = self == null; if ((symbol as MethodSymbol)?.Method.IsStatic == isStatic || symbol is ConstructorSymbol) { CheckArguments(symbol as MemberSymbol, ((MethodBaseSymbol)symbol).Parameters, args, ref ovRes, options); } else if ((symbol as SymbolList)?.HasMethodBase == true) { var methods = symbol as SymbolList; for (int i = 0; i < methods.Symbols.Count; i++) { var m = methods.Symbols[i]; if ((m as MethodSymbol)?.Method.IsStatic == isStatic || m is ConstructorSymbol) { CheckArguments(m as MemberSymbol, ((MethodBaseSymbol)m).Parameters, args, ref ovRes, options); if (ovRes?.Exact == true) { break; } } } } if (ovRes?.Unique == true) { ApplyConversions(args, ovRes); return(ovRes.Symbol); } if (options.HasFlag(BindOptions.AllowDynamic) && expr != null && ovRes?.Valid != true) { if (symbol is DynamicExprSymbol symbolExpr) { expr = self; self = null; Convert(ref expr, Compilation.Get(NativeType.Usual), options); var obj = new Arg(expr ?? LiteralExpr.Bound(Constant.Create(null))); var name = new Arg(symbolExpr.Name); var arguments = new Arg(LiteralArray.Bound(args.Args)); args.Args.Clear(); args.Args.Add(obj); args.Args.Add(name); args.Args.Add(arguments); return(Compilation.Get(WellKnownMembers.XSharp_RT_Functions___InternalSend)); } else if (symbol is DynamicSymbol symbolDynamic) { expr = self; self = null; Convert(ref expr, Compilation.Get(NativeType.Usual), options); var obj = new Arg(expr ?? LiteralExpr.Bound(Constant.Create(null))); var name = new Arg(LiteralExpr.Bound(Constant.Create(symbolDynamic.Name))); var arguments = new Arg(LiteralArray.Bound(args.Args)); args.Args.Clear(); args.Args.Add(obj); args.Args.Add(name); args.Args.Add(arguments); return(Compilation.Get(WellKnownMembers.XSharp_RT_Functions___InternalSend)); } else if (symbol.Type()?.IsUsualOrObject() == true) { self = null; Convert(ref expr, Compilation.Get(NativeType.Usual), options); var obj = new Arg(expr); var name = new Arg(LiteralExpr.Bound(Constant.Create(SystemNames.DelegateInvokeName))); var arguments = new Arg(LiteralArray.Bound(args.Args)); args.Args.Clear(); args.Args.Add(obj); args.Args.Add(name); args.Args.Add(arguments); return(Compilation.Get(WellKnownMembers.XSharp_RT_Functions___InternalSend)); } } return(null); }
internal static CompilationError CtorCallBindError(Expr expr, Symbol symbol, ArgList args, OverloadResult ovRes) { if (ovRes?.Valid != true) { if (symbol is SymbolList) { return(expr.Error(ErrorCode.NoSuitableCtor)); } else if (symbol is ConstructorSymbol) { return(expr.Error(ErrorCode.ArgumentsNotMatchCtor)); } else { return(expr.Error(ErrorCode.CtorNotFound)); } } if (ovRes.Unique == false) { string sMessage1 = ""; string sMessage2 = ""; if (ovRes?.Symbol is ConstructorSymbol msym) { sMessage1 = msym.Signature; } if (ovRes?.Equivalent?.Symbol is ConstructorSymbol msym2) { sMessage2 = msym2.Signature; } return(expr.Error(ErrorCode.AmbiguousCall, sMessage1, sMessage2)); } return(expr.Error(ErrorCode.CtorNotFound)); }
internal MemberSymbol TryBindCall(Expr expr, Symbol symbol, ArgList args, out Expr self, out Expr writeBack, ref OverloadResult ovRes, BindOptions options) { self = (expr as MemberAccessExpr)?.Expr; writeBack = null; bool isStatic = self == null; var matching = new List <OverloadResult>(); if ((symbol as MethodSymbol)?.Method.IsStatic == isStatic || symbol is ConstructorSymbol) { CheckArguments(symbol as MemberSymbol, ((MethodBaseSymbol)symbol).Parameters, args, ref ovRes, options); } else if ((symbol as SymbolList)?.HasMethodBase == true) { var methods = symbol as SymbolList; for (int i = 0; i < methods.Symbols.Count; i++) { var m = methods.Symbols[i]; if ((m as MethodSymbol)?.Method.IsStatic == isStatic || m is ConstructorSymbol) { CheckArguments(m as MemberSymbol, ((MethodBaseSymbol)m).Parameters, args, ref ovRes, options); if (ovRes?.Exact == true) { break; } if (ovRes != null) { if (!matching.Contains(ovRes)) { matching.Add(ovRes); } if (ovRes.Equivalent != null && !matching.Contains(ovRes.Equivalent)) { matching.Add(ovRes.Equivalent); } } } } } if (ovRes?.Unique == true) { ApplyConversions(args, ovRes, out writeBack); return(ovRes.Symbol); } // Add automatic overload resolution if (ovRes != null && !ovRes.Unique && ovRes.Equivalent != null) { var ov1 = ovRes.Symbol; var ov2 = ovRes.Equivalent.Symbol; var func1 = ov1.DeclaringType.FullName; var func2 = ov2.DeclaringType.FullName; if (func1 != func2 && func1.StartsWith("XSharp") && func2.StartsWith("XSharp")) { switch (func1) { case XSharpSpecialNames.XSharpVOFunctionsClass: case XSharpSpecialNames.XSharpDataFunctionsClass: case XSharpSpecialNames.XSharpVFPFunctionsClass: case XSharpSpecialNames.XSharpXPPFunctionsClass: // functions in specific runtime files override generic files return(ovRes.Symbol); case XSharpSpecialNames.XSharpRTFunctionsClass: if (func2 == XSharpSpecialNames.XSharpCoreFunctionsClass) { // functions in specific runtime files override generic files return(ovRes.Symbol); } break; } switch (func2) { case XSharpSpecialNames.XSharpVOFunctionsClass: case XSharpSpecialNames.XSharpDataFunctionsClass: case XSharpSpecialNames.XSharpVFPFunctionsClass: case XSharpSpecialNames.XSharpXPPFunctionsClass: // functions in specific runtime files override generic files return(ovRes.Equivalent.Symbol); case XSharpSpecialNames.XSharpRTFunctionsClass: if (func1 == XSharpSpecialNames.XSharpCoreFunctionsClass) { // functions in specific runtime files override generic files return(ovRes.Equivalent.Symbol); } break; } } } if (matching.Count > 1 && ovRes.Valid && Options.Resolver != null) { var res = AskUserForCorrectOverload(matching, args); if (res != null) { ovRes = res; ApplyConversions(args, ovRes, out writeBack); return(ovRes.Symbol); } } if (options.HasFlag(BindOptions.AllowDynamic) && expr != null && ovRes?.Valid != true) { if (symbol is DynamicExprSymbol symbolExpr) { expr = self; self = null; Convert(ref expr, Compilation.Get(NativeType.Usual), options); ApplyUsualConversions(args, out writeBack); var obj = new Arg(expr ?? LiteralExpr.Bound(Constant.Create(null))); var name = new Arg(symbolExpr.Name); var arguments = ApplyUsualConversions(args, out writeBack); args.Args.Clear(); args.Args.Add(obj); args.Args.Add(name); args.Args.Add(arguments); // todo: Check for ref arguments and handle writeback from arguments array return(Compilation.Get(WellKnownMembers.XSharp_RT_Functions___InternalSend)); } else if (symbol is DynamicSymbol symbolDynamic) { expr = self; self = null; Convert(ref expr, Compilation.Get(NativeType.Usual), options); var obj = new Arg(expr ?? LiteralExpr.Bound(Constant.Create(null))); var name = new Arg(LiteralExpr.Bound(Constant.Create(symbolDynamic.Name))); var arguments = ApplyUsualConversions(args, out writeBack); args.Args.Clear(); args.Args.Add(obj); args.Args.Add(name); args.Args.Add(arguments); // todo: Check for ref arguments and handle writeback from arguments array return(Compilation.Get(WellKnownMembers.XSharp_RT_Functions___InternalSend)); } else if (symbol.Type()?.IsUsualOrObject() == true) { self = null; Convert(ref expr, Compilation.Get(NativeType.Usual), options); ApplyUsualConversions(args, out writeBack); var obj = new Arg(expr); var name = new Arg(LiteralExpr.Bound(Constant.Create(SystemNames.DelegateInvokeName))); var arguments = ApplyUsualConversions(args, out writeBack); args.Args.Clear(); args.Args.Add(obj); args.Args.Add(name); args.Args.Add(arguments); // todo: Check for ref arguments and handle writeback from arguments array return(Compilation.Get(WellKnownMembers.XSharp_RT_Functions___InternalSend)); } } return(null); }
void ApplyConversions(ArgList args, OverloadResult ovRes, out Expr writeBack) { writeBack = null; var parameters = ovRes.Parameters.Parameters; for (int i = 0; i < ovRes.FixedArgs; i++) { var conv = ovRes.Conversions[i]; var e = args.Args[i].Expr; if (conv.Kind != ConversionKind.Identity) { Convert(ref args.Args[i].Expr, FindType(parameters[i].ParameterType), conv); } if (conv is ConversionSymbolToConstant) { Convert(ref args.Args[i].Expr, FindType(parameters[i].ParameterType), BindOptions.Default); } HandleArgWriteBack(conv, e, ref writeBack); } if (ovRes.MissingArgs > 0) { for (int i = ovRes.FixedArgs; i < ovRes.FixedArgs + ovRes.MissingArgs; i++) { var conv = ovRes.Conversions[i]; var a = new Arg(LiteralExpr.Bound(((ConversionSymbolToConstant)conv).Constant)); Convert(ref a.Expr, FindType(parameters[i].ParameterType), BindOptions.Default); args.Args.Add(a); } } else if (ovRes.Parameters.HasParamArray) { var varArgs = new List <Expr>(ovRes.VarArgs); var varArgType = FindType(parameters[ovRes.FixedArgs].ParameterType.GetElementType()); bool hasRefArgs = false; for (int i = ovRes.FixedArgs; i < ovRes.FixedArgs + ovRes.VarArgs; i++) { var conv = ovRes.Conversions[i]; var e = args.Args[i].Expr; Convert(ref e, varArgType, conv); varArgs.Add(e); if (args.Args[i].RefKind != RefKind.None) { hasRefArgs = true; } } var varArg = new Arg(LiteralArray.Bound(varArgs, varArgType)); if (hasRefArgs) { var conv = ConversionSymbol.Create(ConversionSymbol.Create(ConversionKind.Identity), new ConversionToTemp(varArg.Expr.Datatype)); Convert(ref varArg.Expr, varArg.Expr.Datatype, conv); for (int i = ovRes.FixedArgs; i < ovRes.FixedArgs + ovRes.VarArgs; i++) { if (args.Args[i].RefKind != RefKind.None) { HandleVarArgWriteBack(conv, args.Args[i].Expr, i - ovRes.FixedArgs, ref writeBack); } } } while (args.Args.Count > ovRes.FixedArgs) { args.Args.RemoveAt(args.Args.Count - 1); } args.Args.Add(varArg); } void HandleArgWriteBack(ConversionSymbol conv, Expr e, ref Expr wb) { if (conv.IsIndirectRefConversion()) { if (e.Symbol?.HasSetAccess == true || e is AutoVarExpr || e is AliasExpr) { // Handle writeBack Expr t = IdExpr.Bound(conv.IndirectRefConversionTempLocal()); var wc = Conversion(t, e.Datatype, BindOptions.Default); if (wc.Exists) { Convert(ref t, e.Datatype, wc); SymbolExtensions.AddExpr(ref wb, AssignExpr.Bound(e, t, BindOptions.Default)); } } } } void HandleVarArgWriteBack(ConversionSymbol conv, Expr e, int i, ref Expr wb) { if (e.Symbol?.HasSetAccess == true || e is AutoVarExpr || e is AliasExpr) { // Handle writeBack Expr t = IdExpr.Bound(conv.IndirectRefConversionTempLocal()); t = ArrayAccessExpr.Bound(t, ArgList.Bound(LiteralExpr.Bound(Constant.Create(i + 1))), this); var wc = Conversion(t, e.Datatype, BindOptions.Default); if (wc.Exists) { Convert(ref t, e.Datatype, wc); SymbolExtensions.AddExpr(ref wb, AssignExpr.Bound(e, t, BindOptions.Default)); } } } }