public override IEnumerator <RantAction> Run(Sandbox sb) { // Convert arguments to their native types int paramc = _funcInfo.Parameters.Length; var args = new object[_argc]; double d; RantFunctionParameter p; for (int i = 0; i < _argc; i++) { p = GetParameter(i); switch (p.RantType) { // Patterns are passed right to the method case RantFunctionParameterType.Pattern: args[i] = _argActions[i]; break; // Strings are evaluated case RantFunctionParameterType.String: sb.AddOutputWriter(); yield return(_argActions[i]); args[i] = sb.Return().Main; break; // Numbers are evaluated, verified, and converted case RantFunctionParameterType.Number: { sb.AddOutputWriter(); yield return(_argActions[i]); var strNum = sb.Return().Main; if (!Double.TryParse(strNum, out d)) { d = 0; int n; if (Util.ParseInt(strNum, out n)) { d = n; } } args[i] = Convert.ChangeType(d, p.NativeType); break; } // Modes are parsed into enumeration members case RantFunctionParameterType.Mode: { sb.AddOutputWriter(); yield return(_argActions[i]); var strMode = sb.Return().Main; object value; if (!Util.TryParseEnum(p.NativeType, strMode, out value)) { throw new RantRuntimeException(sb.Pattern, _argActions[i].Range, $"Unknown mode value '{strMode}'."); } args[i] = value; break; } // Flags are parsed from strings to enum members and combined with OR. case RantFunctionParameterType.Flags: { var enumType = p.NativeType; sb.AddOutputWriter(); yield return(_argActions[i]); long flags = 0; var strFlags = sb.Return().Main; object value; foreach (var flag in strFlags.Split(new [] { ' ' }, StringSplitOptions.RemoveEmptyEntries)) { if (!Util.TryParseEnum(enumType, flag, out value)) { throw new RantRuntimeException(sb.Pattern, _argActions[i].Range, $"Unknown flag value '{flag}'."); } flags |= Convert.ToInt64(value); } args[i] = Enum.ToObject(enumType, flags); break; } } } // Invoke the function IEnumerator <RantAction> requester; if (_funcInfo.HasParamArray) { int required = paramc - 1; int parrayCount = _argc - required; var parray = Array.CreateInstance(_funcInfo.Parameters[required].NativeType, parrayCount); Array.Copy(args, required, parray, 0, parrayCount); requester = _funcInfo.Invoke(sb, args.Take(required).Concat(new[] { parray }).ToArray()); } else { requester = _funcInfo.Invoke(sb, args); } while (requester.MoveNext()) { yield return(requester.Current); } }
public override IEnumerator <RST> Run(Sandbox sb) { // Convert arguments to their native types int paramc = _funcInfo.Parameters.Length; var args = new object[_argc]; RantFunctionParameter p; for (int i = 0; i < _argc; i++) { p = GetParameter(i); switch (p.RantType) { // Patterns are passed right to the method case RantFunctionParameterType.Pattern: args[i] = _args[i]; break; // Strings are evaluated case RantFunctionParameterType.String: sb.AddOutputWriter(); yield return(_args[i]); args[i] = sb.Return().Main; break; // RantObjects are evaluated and fetched by name case RantFunctionParameterType.RantObject: { sb.AddOutputWriter(); yield return(_args[i]); var name = sb.Return().Main; args[i] = sb.Objects[name] ?? throw new RantRuntimeException(sb, _args[i], "err-runtime-missing-var", name); break; } // Numbers are evaluated, verified, and converted case RantFunctionParameterType.Number: { sb.AddOutputWriter(); yield return(_args[i]); string strNum = sb.Return().Main; if (!Util.ParseDouble(strNum, out double d)) { d = 0; if (Util.ParseInt(strNum, out int n)) { d = n; } else { throw new RantRuntimeException(sb, _args[i], "err-runtime-invalid-arg", strNum, p.Name, p.RantType.ToString().ToLower()); } } args[i] = Convert.ChangeType(d, p.NativeType); break; } case RantFunctionParameterType.Boolean: { sb.AddOutputWriter(); yield return(_args[i]); var val = sb.Return().Main; if (val.Equals("true", StringComparison.InvariantCultureIgnoreCase)) { args[i] = true; } else if (val.Equals("false", StringComparison.InvariantCultureIgnoreCase)) { args[i] = false; } else { throw new RantRuntimeException(sb, _args[i], "err-runtime-invalid-arg", val, p.Name, p.RantType.ToString().ToLower()); } break; } // Modes are parsed into enumeration members case RantFunctionParameterType.Mode: { sb.AddOutputWriter(); yield return(_args[i]); string strMode = sb.Return().Main; if (!Util.TryParseEnum(p.NativeType, strMode, out object value)) { throw new RantRuntimeException(sb, _args[i].Location, "err-runtime-unknown-mode", strMode, Util.GetEnumListString(p.NativeType)); } args[i] = value; break; } // Flags are parsed from strings to enum members and combined with OR. case RantFunctionParameterType.Flags: { var enumType = p.NativeType; sb.AddOutputWriter(); yield return(_args[i]); long flags = 0; string strFlags = sb.Return().Main; foreach (string flag in strFlags.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)) { if (!Util.TryParseEnum(enumType, flag, out object value)) { throw new RantRuntimeException(sb, _args[i].Location, "err-runtime-unknown-flag", flag, Util.GetEnumListString(enumType)); } flags |= Convert.ToInt64(value); } args[i] = Enum.ToObject(enumType, flags); break; } } } // Invoke the function IEnumerator <RST> requester; if (_funcInfo.HasParamArray) { int required = paramc - 1; int parrayCount = _argc - required; var parray = Array.CreateInstance(_funcInfo.Parameters[required].NativeType, parrayCount); Array.Copy(args, required, parray, 0, parrayCount); requester = _funcInfo.Invoke(sb, args.Take(required).Concat(new[] { parray }).ToArray()); } else { requester = _funcInfo.Invoke(sb, args); } while (requester.MoveNext()) { yield return(requester.Current); } }