Value len(FunctionArguments arguments, SymbolTable symbol_table)
        {
            arguments.check_num_args(1);
            var val = arguments.get_value_argument(0, null, null, symbol_table);

            if (val.Type == ValueType.String)
            {
                var val_str = (StringValue)val;
                return(new DynamicValue(val_str.value.Length));
            }
            else if (val.Type == ValueType.List)
            {
                var val_list = (ListValue)val;
                return(new DynamicValue(val_list.Count));
            }
            else if (val.Type == ValueType.Dictionary)
            {
                var dict_val = (DictionaryValue)val;
                return(new DynamicValue(dict_val.dict.Keys.Count));
            }
            else if (val.Type == ValueType.Enumerator)
            {
                var enum_val = (EnumeratorValue)val;
                return(new DynamicValue(enum_val.Count));
            }
            else
            {
                throw new Exception("len(" + val.ToString() + ") is not supported.");
            }
        }
        Value str(FunctionArguments arguments, SymbolTable symbol_table)
        {
            arguments.check_num_args(1);
            var val = arguments.get_value_argument(0, null, null, symbol_table);

            return(new StringValue(val.ToString()));
        }
        Value python_int(FunctionArguments arguments, SymbolTable symbol_table)
        {
            arguments.check_num_args(1);
            var val = arguments.get_value_argument(0, null, null, symbol_table);


            if (val.Type == ValueType.Dynamic)
            {
                var val_dyn = (DynamicValue)val;
                if (val_dyn.value is int)
                {
                    return(val_dyn);
                }

                else if (val_dyn.value is double)
                {
                    if (val_dyn.value >= 0)
                    {
                        return(new DynamicValue((int)Math.Floor(val_dyn.value)));
                    }
                    else
                    {
                        return(new DynamicValue((int)Math.Floor(val_dyn.value) + 1));
                    }
                }

                else if (val_dyn.value is bool)
                {
                    if (val_dyn.value == true)
                    {
                        return(new DynamicValue(1));
                    }
                    if (val_dyn.value == false)
                    {
                        return(new DynamicValue(0));
                    }
                }
            }
            else if (val.Type == ValueType.String)
            {
                var  val_str = (StringValue)val;
                int  result;
                bool success = int.TryParse(val_str.value, out result);

                if (success)
                {
                    return(new DynamicValue(result));
                }
                else
                {
                    throw new Exception("Failed to convert " + val_str.value + " to int.");
                }
            }
            else
            {
                throw new Exception("int(" + val.Type + ") is not supported.");
            }

            throw new Exception("int() used in an unsupported way.");
        }
        /// <summary>
        /// C# version of Python's dictionary::get().
        /// </summary>
        static Value get(Dictionary <Value, Value> dict, FunctionArguments arguments, SymbolTable symbol_table)
        {
            arguments.check_num_args_minimum(1);
            arguments.check_num_args_maximum(2);

            var key         = arguments.get_value_argument(0, null, null, symbol_table);
            var default_val = arguments.get_value_argument(1, null, NoneValue.NONE, symbol_table);

            if (dict.ContainsKey(key))
            {
                return(dict[key]);
            }
            else
            {
                return(default_val);
            }
        }
        Value list(FunctionArguments arguments, SymbolTable symbol_table)
        {
            arguments.check_num_args(1);
            var val = arguments.get_value_argument(0, null, null, symbol_table);

            // Handle list(string)
            if (val.Type == ValueType.String)
            {
                string str      = ((StringValue)val).value;
                var    new_list = new List <Value>();

                foreach (char c in str)
                {
                    new_list.Add(new StringValue(c.ToString()));
                }

                return(new ListValue(new_list));
            }

            // Handle list(list)
            else if (val.Type == ValueType.List)
            {
                // return a shallow copy of "val"
                var list_val = (ListValue)val;
                return(list_val.get_shallow_copy());
            }

            // Handle list(range)
            else if (val.Type == ValueType.Range)
            {
                var range_val = (RangeValue)val;
                var val_list  = range_val.get_list();
                return(new ListValue(val_list));
            }

            // Handle list(enumerator)
            else if (val.Type == ValueType.Enumerator)
            {
                var enumerator = ((EnumeratorValue)val).enumerator;
                var list       = new List <Value>();

                enumerator.Reset();

                while (enumerator.MoveNext())
                {
                    list.Add(enumerator.Current);
                }

                return(new ListValue(list));
            }

            else
            {
                throw new Exception("list(" + val.ToString() + ") is not supported.");
            }
        }
        /// <summary>
        /// C# version of Python's dictionary::update(). This version of
        /// update() expects a single dictionary.
        /// </summary>
        static NoneValue update(Dictionary <Value, Value> dict, FunctionArguments arguments, SymbolTable symbol_table)
        {
            arguments.check_num_args(1);

            var d2 = arguments.get_value_argument(0, null, null, symbol_table);

            if (d2.Type != ValueType.Dictionary)
            {
                throw new Exception("This version of dictionary::update(dict) requires a dictionary argument.");
            }

            var dict2 = ((DictionaryValue)d2).dict;

            foreach (var key in dict2.Keys)
            {
                dict[key] = ListValue.shallow_copy(dict2[key]);
            }

            return(NoneValue.NONE);
        }