Пример #1
0
        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);
            }
        }
Пример #2
0
        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);
            }
        }