private static string AppendTemplateArguments(XDoc args, out bool simple) {
            StringBuilder code = new StringBuilder();
            if(args.IsEmpty) {
                simple = true;
            } else {
                List<XDoc> list = args.ToList();
                simple = true;

                // check if arguments are neither strings nor numbers
                foreach(XDoc arg in list) {
                    string value = AsArgument(arg.AsXmlNode);
                    DekiScriptExpression expr = SafeParse(value);
                    if(!(expr is DekiScriptString) && !(expr is DekiScriptNumber)) {
                        simple = false;
                        break;
                    }
                }

                // check if all entries are simple strings
                if(simple) {
                    bool listOnly = true;
                    Hashtable map = new Hashtable();
                    for(int i = 0; i < list.Count; i++) {
                        DekiScriptExpression expr = SafeParse(AsArgument(list[i].AsXmlNode));
                        if(expr is DekiScriptString) {
                            string arg = ((DekiScriptString)expr).Value;
                            int equalIndex = arg.IndexOf("=");
                            if(equalIndex > 0) {
                                string id = arg.Substring(0, equalIndex).Trim();
                                if(ARG_REGEX.IsMatch(id)) {
                                    listOnly = false;
                                    string value = arg.Substring(equalIndex + 1, arg.Length - equalIndex - 1);
                                    double number;
                                    if(double.TryParse(value, out number)) {
                                        map[id] = number;
                                    } else {
                                        map[id] = value;
                                    }
                                } else {
                                    map[i.ToString()] = arg;
                                }
                            } else {
                                map[i.ToString()] = arg;
                            }
                        } else if(expr is DekiScriptNumber) {
                            double arg = ((DekiScriptNumber)expr).Value;
                            map[i.ToString()] = arg;
                        } else {
                            throw new Exception("should never happen");
                        }
                    }

                    // check if all indices are simple numbers
                    if(listOnly) {
                        ArrayList items = new ArrayList();
                        for(int i = 0; i < map.Count; ++i) {
                            items.Add(map[i.ToString()]);
                        }
                        code.Append(new DekiScriptList(items).ToString());
                    } else {
                        code.Append(new DekiScriptMap(map).ToString());
                    }
                } else {
                    code.Append("mediawiki.args([");
                    bool first = true;
                    foreach(XDoc arg in args) {
                        if(!first) {
                            code.Append(", ");
                        }
                        first = false;
                        code.Append(AsArgument(arg.AsXmlNode));
                    }
                    code.Append("])");
                }
            }
            return code.ToString();
        }