public VariableTBase Invoke(string name, VariableTBase[] args) { List <Invokable> invs; lock (functions) { if (!functions.ContainsKey(name)) { access.WriteText(ConsoleErrorMessages.FunctionNotFound); throw new Exceptions.ShellFunctionNotFound(); } else { invs = functions[name]; } } foreach (Invokable ivb in invs) { ArgResult rs = CheckPopulateArgs(args, ivb); if (!rs.IsCorrect) { continue; } MethodInfo minf = ivb.CallStd.generic ? rs.genCr : ivb.MInfo; object o = minf.Invoke(null, rs.arguments); VariableTBase vb = (VariableTBase)o; return(vb); } throw new Exceptions.ShellFunctionNotFound(); return(null); }
/// <summary> /// Checks for correct arguments and populates the argument array. /// </summary> /// <param name="args">Given arguments.</param> /// <param name="inv">Invokable to test.</param> ArgResult CheckPopulateArgs(VariableTBase[] args, Invokable inv) { if (inv.CallStd == null) { FindCallStd(inv); } var Arguments = inv.MInfo.GetParameters(); int usesCFunc; /* Check whether it uses the ConsoleAccess structure and also check it has at least as many arguments as the function inputs */ if (inv.CallStd.cfunc) { if (Arguments.Length > args.Length + 1) { return new ArgResult() { IsCorrect = false, ex = new Exceptions.ShellArgumentMismatch(ConsoleErrorMessages.TooFewArguments) } } ; else { usesCFunc = 1; } } else { if (Arguments.Length > args.Length) { return new ArgResult() { IsCorrect = false, ex = new Exceptions.ShellArgumentMismatch(ConsoleErrorMessages.TooFewArguments) } } ; else { usesCFunc = 0; } } /* Get rid of the case where there are no function inputs */ if (Arguments.Length == usesCFunc) { if (args.Length != 0) { return new ArgResult() { IsCorrect = false, ex = new Exceptions.ShellArgumentMismatch(ConsoleErrorMessages.NonemptyArguments) } } ; else { return new ArgResult() { IsCorrect = true, arguments = new object[0] } }; } /* Check if it uses a variable number of arguments */ int hasparams = inv.CallStd.hp1 | inv.CallStd.hp2 ? 1 : 0; if (hasparams == 0 & (args.Length + usesCFunc > Arguments.Length)) { return new ArgResult() { IsCorrect = false, ex = new Exceptions.ShellArgumentMismatch(ConsoleErrorMessages.TooManyArgsNotVarargs) } } ; /* Prepare ArgResult */ ArgResult lg = new ArgResult(); lg.Extracted = new List <Tuple <int, object> > (); lg.arguments = new object[Arguments.Length]; if (inv.CallStd.generic) { try { lg.genCr = CreateGenericMethod(args, inv); } catch (Exceptions.ShellArgumentMismatch e) { return(new ArgResult() { IsCorrect = false, ex = e }); } Arguments = lg.genCr.GetParameters(); } int i; /* Check if the arguments match the function */ for (i = 0; i + hasparams + usesCFunc < Arguments.Length; i++) { if (!Arguments[i].ParameterType.IsInstanceOfType(args[i])) { var z = GetVar(args[i], Arguments[i].ParameterType); if (z == null) { return new ArgResult() { IsCorrect = false, ex = new Exceptions.ShellArgumentMismatch(ConsoleErrorMessages.ArgumentTypeMismatch) } } ; lg.Extracted.Add(new Tuple <int, object> (i, z.Item2)); lg.arguments[i] = z.Item2; } else { lg.arguments[i] = args[i]; } } /* Check for the 2 possible params cases */ if (inv.CallStd.hp1) { List <VariableTBase> vb = new List <VariableTBase> (); Type z = Arguments[Arguments.Length - 1 - usesCFunc].ParameterType.GetElementType(); Type tz = this.GetType(); MethodInfo eim = tz.GetMethod("MakeArrayT", BindingFlags.NonPublic | BindingFlags.Static); MethodInfo im = eim.MakeGenericMethod(z); for (; i < args.Length; i++) { vb.Add(args[i]); } lg.arguments[Arguments.Length - 1 - usesCFunc] = im.Invoke(null, new object[] { vb }); } if (inv.CallStd.hp2) { List <object> sobj = new List <object> (); for (; i + usesCFunc < Arguments.Length; i++) { object[] o2; var z = GetVar(args[i], Arguments[i].ParameterType); if (z != null) { sobj.Add(z.Item2); } else { z = GetVar(args[i], Arguments[i].ParameterType.GetElementType()); if (z == null) { return new ArgResult() { IsCorrect = false, ex = new Exceptions.ShellArgumentMismatch(ConsoleErrorMessages.ArgumentTypeMismatch) } } ; o2 = (object[])z.Item2; sobj.AddRange(o2); } lg.Extracted.Add(new Tuple <int, object> (i, z.Item2)); } lg.arguments[Arguments.Length - 1 - usesCFunc] = sobj.ToArray(); } lg.IsCorrect = true; return(lg); } /// <summary> /// Gets the variable type and embedded object. /// </summary> /// <param name="vb">The input variable.</param> /// <param name="tp">The expected argument type.</param> Tuple <Type, object> GetVar(VariableTBase vb, Type tp) { Type tc = tp; while (tc != null && tc != typeof(object)) { var cur = tc.IsGenericType ? tc.GetGenericTypeDefinition() : tc; if (typeof(Variable <>) == cur) { return(new Tuple <Type, object> (tc.GetGenericArguments()[0], tc.GetField("obj").GetValue(vb))); } tc = tc.BaseType; } return(null); }