/// <summary> /// Given a list of args (during a new instance call), parse out the first one as the class name, /// and convert the rest into an object array suitable for passing through reflection. /// </summary> private static (Type type, object[] varargs) ParseArgsForConstructorInterop(VarArgs args) { Cons list = args.cons; Val first = list?.first ?? Val.NIL; Type type = GetTypeFromNameOrObject(first); object[] varargs = TurnConsIntoBoxedArray(list?.rest); return(type, varargs); }
/// <summary> /// Parse out the first argument as a type based on name or instance, /// and the second as a member that's either a field or a property field. /// </summary> private static (Type type, string member) ParseArgsForMemberSearch(VarArgs args) { Cons list = args.cons; Val first = list?.first ?? Val.NIL; Val second = list?.second ?? Val.NIL; Type type = GetTypeFromNameOrObject(first); string member = GetStringOrSymbolName(second); return(type, member); }
///// <summary> Performs a right fold on the array: +, 0, [1, 2, 3] => (1 + (2 + (3 + 0))) </summary> private static Val FoldRight(Func <Val, Val, Val> fn, Val baseElement, VarArgs args) { var result = baseElement; var elements = args.ToNativeList(); for (int i = elements.Count - 1; i >= 0; i--) { result = fn(elements[i], result); } return(result); }
///// <summary> Performs a left fold on the array: +, 0, [1, 2, 3] => (((0 + 1) + 2) + 3) </summary> private static Val FoldLeft(Func <Val, Val, Val> fn, Val baseElement, VarArgs args) { var result = baseElement; var elements = args.ToNativeList(); for (int i = 0, len = elements.Count; i < len; i++) { result = fn(result, elements[i]); } return(result); }
// // // dotnet interop public static Val DotDot(Context _, VarArgs args) { var arglist = args.ToNativeList().SelectMany(SplitSymbol).ToList(); var gotone = arglist.Count > 0; if (!gotone) { return(Val.NIL); } int i = 0; var current = arglist[i++]; do { var nextSymbol = TakeNextSymbolOrNull(); var nonSymbols = TakeNonSymbols().ToList(); current = TryReflectionStep(current, nextSymbol, nonSymbols); } while (i < arglist.Count); return(current); Symbol TakeNextSymbolOrNull() { var results = TakeSymbols(true).Take(1); return(results.FirstOrDefault().AsSymbolOrNull); } IEnumerable <Val> TakeNonSymbols() { return(TakeSymbols(false)); } IEnumerable <Val> TakeSymbols(bool expected) { while (i < arglist.Count) { var next = arglist[i]; if (next.IsSymbol == expected) { i++; yield return(next); } else { break; } } } }
/// <summary> /// Given an instance as the first argument, parse out its type, /// and parse the second arg as a member that's either a field or a property field. /// If the setter flag is set, it also parses out the third element as the new value. /// </summary> private static (object instance, Type type, string member, Val third, Val fourth) ParseSetterArgs(VarArgs args, bool setter) { Cons list = args.cons; Val first = list?.first ?? Val.NIL; Val second = list?.second ?? Val.NIL; Val third = (setter && list != null) ? list.third : Val.NIL; Val fourth = (setter && list != null && list.afterThird.IsNotNil) ? list.fourth : Val.NIL; var instance = first.AsBoxedValue; Type type = instance?.GetType(); string member = GetStringOrSymbolName(second); return(instance, type, member, third, fourth); }
/// <summary> /// Given a list of args (for a function call), parse out the first one as the type we're referring to, /// second as method name, and convert the rest into an object array suitable for passing through reflection. /// </summary> private static (MethodInfo method, object instance, object[] varargs) ParseArgsForMethodCall(VarArgs args) { Cons list = args.cons; Val first = list?.first ?? Val.NIL; Val second = list?.second ?? Val.NIL; object instance = first.AsObjectOrNull; MethodInfo method = second.GetObjectOrNull <MethodInfo>(); object[] varargs = TurnConsIntoBoxedArray(list?.afterSecond); return(method, instance, varargs); }
/// <summary> /// Given a list of args (during a method search), parse out the first one as the name class, /// second as method name, and convert the rest into an object array suitable for passing through reflection. /// </summary> private static (Type type, string member, object[] varargs) ParseArgsForMethodSearch(VarArgs args) { Cons list = args.cons; Val first = list?.first ?? Val.NIL; Val second = list?.second ?? Val.NIL; Type type = GetTypeFromNameOrObject(first); string member = GetStringOrSymbolName(second); object[] varargs = TurnConsIntoBoxedArray(list?.afterSecond); return(type, member, varargs); }
/// <summary> /// Given an instance as the first argument, parse out its type, /// and parse the second arg as a member that's either a field or a property field. /// If the setter flag is set, it also parses out the third element as the new value. /// </summary> private static (object instance, Type type, string member, Val third) ParseMemberFromInstance(VarArgs args, bool setter) { Cons list = args.cons; Val first = list?.first ?? Val.NIL; Val second = list?.second ?? Val.NIL; Val third = (setter && list != null) ? list.third : Val.NIL; var instance = first.AsBoxedValue; Type type = instance?.GetType(); string member = GetStringOrSymbolName(second); return(instance, type, member, third); }