Keyword arguments
This commit is contained in:
parent
035c482c33
commit
4e0169a45b
@ -59,16 +59,26 @@ private:
|
||||
class Callback : public moo::RefCounted<Callback>
|
||||
{
|
||||
public:
|
||||
virtual Variant run(const ArgArray &args) = 0;
|
||||
virtual Variant run(const ArgList &args) = 0;
|
||||
virtual void on_connect() = 0;
|
||||
virtual void on_disconnect() = 0;
|
||||
};
|
||||
|
||||
struct ArgSet
|
||||
{
|
||||
ArgList pos;
|
||||
ArgDict kw;
|
||||
|
||||
ArgSet() {}
|
||||
explicit ArgSet(const ArgList &pos) : pos(pos) {}
|
||||
ArgSet(const ArgList &pos, const ArgDict &kw) : pos(pos), kw(kw) {}
|
||||
};
|
||||
|
||||
class Script
|
||||
{
|
||||
public:
|
||||
static HObject get_app_obj() NOTHROW;
|
||||
static Result call_method(HObject obj, const String &meth, const ArgArray &args, Variant &ret) NOTHROW;
|
||||
static Result call_method(HObject obj, const String &meth, const ArgSet &args, Variant &ret) NOTHROW;
|
||||
static Result connect_callback(HObject obj, const String &event, moo::SharedPtr<Callback> cb, gulong &id) NOTHROW;
|
||||
static Result disconnect_callback(HObject obj, gulong id) NOTHROW;
|
||||
};
|
||||
|
@ -65,8 +65,8 @@ static moo::Vector<String> get_string_list(const Variant &val)
|
||||
VariantArray ar;
|
||||
if (val.vt() == VtArray)
|
||||
ar = val.value<VtArray>();
|
||||
else if (val.vt() == VtArgs)
|
||||
ar = val.value<VtArgs>();
|
||||
else if (val.vt() == VtArgList)
|
||||
ar = val.value<VtArgList>();
|
||||
else
|
||||
Error::raise("list expected");
|
||||
moo::Vector<String> ret;
|
||||
@ -120,8 +120,8 @@ static void get_pair(const Variant &val, Variant &elm1, Variant &elm2)
|
||||
VariantArray ar;
|
||||
if (val.vt() == VtArray)
|
||||
ar = val.value<VtArray>();
|
||||
else if (val.vt() == VtArgs)
|
||||
ar = val.value<VtArgs>();
|
||||
else if (val.vt() == VtArgList)
|
||||
ar = val.value<VtArgList>();
|
||||
else
|
||||
Error::raise("pair of values expected");
|
||||
if (ar.size() != 2)
|
||||
@ -172,6 +172,155 @@ void Application::quit()
|
||||
moo_app_quit(moo_app_get_instance());
|
||||
}
|
||||
|
||||
struct DialogOptions
|
||||
{
|
||||
String title;
|
||||
String dialog_id;
|
||||
String icon;
|
||||
String buttons;
|
||||
gint64 width;
|
||||
gint64 height;
|
||||
gint64 timeout;
|
||||
};
|
||||
|
||||
struct FileDialogOptions
|
||||
{
|
||||
String filename;
|
||||
bool multiple;
|
||||
bool directory;
|
||||
bool save;
|
||||
};
|
||||
|
||||
struct ListDialogOptions
|
||||
{
|
||||
moo::Vector<String> columns;
|
||||
moo::Vector<String> data;
|
||||
bool checklist;
|
||||
bool radiolist;
|
||||
bool editable;
|
||||
bool show_header;
|
||||
String return_column;
|
||||
};
|
||||
|
||||
struct MessageDialogOptions
|
||||
{
|
||||
String kind;
|
||||
String text;
|
||||
};
|
||||
|
||||
struct EntryDialogOptions
|
||||
{
|
||||
String text;
|
||||
String entry_text;
|
||||
bool hide;
|
||||
};
|
||||
|
||||
struct TextDialogOptions
|
||||
{
|
||||
String text;
|
||||
String info_text;
|
||||
String filename;
|
||||
bool editable;
|
||||
};
|
||||
|
||||
static Variant show_file_dialog(G_GNUC_UNUSED const FileDialogOptions &dopts, G_GNUC_UNUSED const DialogOptions &opts)
|
||||
{
|
||||
Error::raise("not implemented");
|
||||
}
|
||||
|
||||
static Variant show_list_dialog(G_GNUC_UNUSED const ListDialogOptions &dopts, G_GNUC_UNUSED const DialogOptions &opts)
|
||||
{
|
||||
Error::raise("not implemented");
|
||||
}
|
||||
|
||||
static Variant show_message_dialog(G_GNUC_UNUSED const MessageDialogOptions &dopts, G_GNUC_UNUSED const DialogOptions &opts)
|
||||
{
|
||||
Error::raise("not implemented");
|
||||
}
|
||||
|
||||
static Variant show_entry_dialog(G_GNUC_UNUSED const EntryDialogOptions &dopts, G_GNUC_UNUSED const DialogOptions &opts)
|
||||
{
|
||||
Error::raise("not implemented");
|
||||
}
|
||||
|
||||
static Variant show_text_dialog(G_GNUC_UNUSED const TextDialogOptions &dopts, G_GNUC_UNUSED const DialogOptions &opts)
|
||||
{
|
||||
Error::raise("not implemented");
|
||||
}
|
||||
|
||||
/// @item Application.dialog()
|
||||
/// show a dialog.
|
||||
Variant Application::dialog(const ArgSet &args)
|
||||
{
|
||||
if (!args.pos.empty())
|
||||
Error::raisef("in function %s, no positional arguments expected",
|
||||
(const char*) current_func().name);
|
||||
|
||||
DialogOptions opts;
|
||||
opts.title = get_kwarg_string_opt(args, "title");
|
||||
opts.dialog_id = get_kwarg_string_opt(args, "id");
|
||||
opts.icon = get_kwarg_string_opt(args, "icon");
|
||||
opts.buttons = get_kwarg_string_opt(args, "buttons");
|
||||
opts.width = get_kwarg_int_opt(args, "width", -1);
|
||||
opts.height = get_kwarg_int_opt(args, "height", -1);
|
||||
opts.timeout = get_kwarg_int_opt(args, "timeout", -1);
|
||||
|
||||
String kind = get_kwarg_string(args, "kind");
|
||||
|
||||
if (kind == "file" || kind == "file-selection")
|
||||
{
|
||||
FileDialogOptions dopts;
|
||||
dopts.filename = get_kwarg_string_opt(args, "filename");
|
||||
dopts.multiple = get_kwarg_bool_opt(args, "multiple");
|
||||
dopts.directory = get_kwarg_bool_opt(args, "directory");
|
||||
dopts.save = get_kwarg_bool_opt(args, "save");
|
||||
return show_file_dialog(dopts, opts);
|
||||
}
|
||||
|
||||
if (kind == "list")
|
||||
{
|
||||
ListDialogOptions dopts;
|
||||
dopts.columns = get_string_list(args.kw.value("column"));
|
||||
dopts.data = get_string_list(args.kw.value("data"));
|
||||
dopts.checklist = get_kwarg_bool_opt(args, "checklist");
|
||||
dopts.radiolist = get_kwarg_bool_opt(args, "radiolist");
|
||||
dopts.editable = get_kwarg_bool_opt(args, "editable");
|
||||
dopts.show_header = get_kwarg_bool_opt(args, "show_header");
|
||||
dopts.return_column = get_kwarg_string_opt(args, "return_column");
|
||||
return show_list_dialog(dopts, opts);
|
||||
}
|
||||
|
||||
if (kind == "error" || kind == "warning" || kind == "question" || kind == "information")
|
||||
{
|
||||
MessageDialogOptions dopts;
|
||||
dopts.kind = kind;
|
||||
dopts.text = get_kwarg_string(args, "text");
|
||||
return show_message_dialog(dopts, opts);
|
||||
}
|
||||
|
||||
if (kind == "entry" || kind == "text-entry")
|
||||
{
|
||||
EntryDialogOptions dopts;
|
||||
dopts.text = get_kwarg_string_opt(args, "text");
|
||||
dopts.entry_text = get_kwarg_string_opt(args, "entry_text");
|
||||
dopts.hide = get_kwarg_bool_opt(args, "hide");
|
||||
return show_entry_dialog(dopts, opts);
|
||||
}
|
||||
|
||||
if (kind == "text" || kind == "text-info")
|
||||
{
|
||||
TextDialogOptions dopts;
|
||||
dopts.text = get_kwarg_string_opt(args, "text");
|
||||
dopts.info_text = get_kwarg_string_opt(args, "info_text");
|
||||
dopts.filename = get_kwarg_string_opt(args, "filename");
|
||||
dopts.editable = get_kwarg_bool_opt(args, "editable");
|
||||
return show_text_dialog(dopts, opts);
|
||||
}
|
||||
|
||||
Error::raisef("in function %s, invalid dialog kind '%s'",
|
||||
(const char*) current_func().name, (const char*) kind);
|
||||
}
|
||||
|
||||
///
|
||||
/// @end table
|
||||
///
|
||||
@ -873,7 +1022,7 @@ VariantArray Document::selection()
|
||||
/// @item Document.set_selection(bounds_as_list)
|
||||
/// @item Document.set_selection(start, end)
|
||||
/// select text.
|
||||
void Document::set_selection(const ArgArray &args)
|
||||
void Document::set_selection(const ArgList &args)
|
||||
{
|
||||
GtkTextBuffer *buf = buffer(this);
|
||||
GtkTextIter start, end;
|
||||
@ -985,7 +1134,7 @@ String Document::char_at_pos(gint64 pos)
|
||||
/// returns text in the range [@param{start}, @param{end}), @param{end} not
|
||||
/// included. Example: @code{doc.text(doc.start_pos(), doc.end_pos())} is
|
||||
/// equivalent @code{to doc.text()}.
|
||||
String Document::text(const ArgArray &args)
|
||||
String Document::text(const ArgList &args)
|
||||
{
|
||||
if (args.size() == 0)
|
||||
{
|
||||
@ -1009,7 +1158,7 @@ String Document::text(const ArgArray &args)
|
||||
/// @item Document.insert_text(pos, text)
|
||||
/// insert text into the document. If @param{pos} is not given, insert at
|
||||
/// cursor position.
|
||||
void Document::insert_text(const ArgArray &args)
|
||||
void Document::insert_text(const ArgList &args)
|
||||
{
|
||||
String text;
|
||||
GtkTextIter iter;
|
||||
@ -1112,7 +1261,7 @@ void Document::paste()
|
||||
/// @item Document.select_text(bounds_as_list)
|
||||
/// @item Document.select_text(start, end)
|
||||
/// select text, same as @method{set_selection()}.
|
||||
void Document::select_text(const ArgArray &args)
|
||||
void Document::select_text(const ArgList &args)
|
||||
{
|
||||
GtkTextIter start, end;
|
||||
GtkTextBuffer *buf = buffer(this);
|
||||
@ -1139,7 +1288,7 @@ void Document::select_text(const ArgArray &args)
|
||||
/// @item Document.select_lines(first, last)
|
||||
/// select lines from @param{first} to @param{last}, @emph{including}
|
||||
/// @param{last}.
|
||||
void Document::select_lines(const ArgArray &args)
|
||||
void Document::select_lines(const ArgList &args)
|
||||
{
|
||||
Index first_line, last_line;
|
||||
|
||||
@ -1198,7 +1347,7 @@ static void get_select_lines_range(const VariantArray &args, GtkTextBuffer *buf,
|
||||
/// @item Document.select_lines_at_pos(bounds_as_list)
|
||||
/// @item Document.select_lines_at_pos(start, end)
|
||||
/// select lines: similar to @method{select_text}, but select whole lines.
|
||||
void Document::select_lines_at_pos(const ArgArray &args)
|
||||
void Document::select_lines_at_pos(const ArgList &args)
|
||||
{
|
||||
GtkTextBuffer *buf = buffer(this);
|
||||
GtkTextIter start, end;
|
||||
|
@ -43,8 +43,10 @@ inline const char *get_argument_type_name(VariantType vt)
|
||||
return "string";
|
||||
case VtArray:
|
||||
return "list";
|
||||
case VtArgs:
|
||||
case VtArgList:
|
||||
return "arglist";
|
||||
case VtArgDict:
|
||||
return "argdict";
|
||||
case VtDict:
|
||||
return "dict";
|
||||
case VtObject:
|
||||
@ -62,17 +64,26 @@ NORETURN inline void invalid_argument_type(const char *arg, VariantType vt_expec
|
||||
(const char*) current_func().name, arg, type_expected, type_actual);
|
||||
}
|
||||
|
||||
NORETURN inline void missing_argument(const char *arg)
|
||||
{
|
||||
Error::raisef("in function %s, missing argument '%s'",
|
||||
(const char*) current_func().name, arg);
|
||||
}
|
||||
|
||||
#define DEFINE_GET_ARG_SIMPLE(Vt, Type, get_arg_func, wrap_func) \
|
||||
inline Type get_arg_func(const Variant &var, const char *arg) \
|
||||
{ \
|
||||
if (var.vt() == VtVoid) \
|
||||
missing_argument(arg); \
|
||||
if (var.vt() != Vt) \
|
||||
invalid_argument_type(arg, Vt, var.vt()); \
|
||||
return var.value<Vt>(); \
|
||||
} \
|
||||
inline Type get_arg_func##_opt(const Variant &var, const char *arg) \
|
||||
inline Type get_arg_func##_opt(const Variant &var, const char *arg, \
|
||||
const Type &dflt=Type()) \
|
||||
{ \
|
||||
if (var.vt() == VtVoid) \
|
||||
return Type(); \
|
||||
return dflt; \
|
||||
else if (var.vt() != Vt) \
|
||||
invalid_argument_type(arg, Vt, var.vt()); \
|
||||
else \
|
||||
@ -129,6 +140,11 @@ inline Variant wrap_index(gint64 val)
|
||||
return Variant(Index(val));
|
||||
}
|
||||
|
||||
inline Variant wrap_variant(const Variant &val)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
inline Variant get_arg_variant(const Variant &var, const char *)
|
||||
{
|
||||
return var;
|
||||
@ -179,6 +195,30 @@ inline Variant wrap_object(Object *obj)
|
||||
return HObject(obj ? obj->id() : 0);
|
||||
}
|
||||
|
||||
inline String get_kwarg_string(const ArgSet &args, const char *argname)
|
||||
{
|
||||
return get_arg_string(args.kw.value(argname), argname);
|
||||
}
|
||||
|
||||
inline String get_kwarg_string_opt(const ArgSet &args, const char *argname)
|
||||
{
|
||||
return get_arg_string_opt(args.kw.value(argname), argname);
|
||||
}
|
||||
|
||||
inline gint64 get_kwarg_int_opt(const ArgSet &args, const char *argname, int dflt)
|
||||
{
|
||||
Variant v = args.kw.value(argname);
|
||||
if (v.vt() == VtVoid)
|
||||
return dflt;
|
||||
else
|
||||
return get_arg_int(v, argname);
|
||||
}
|
||||
|
||||
inline bool get_kwarg_bool_opt(const ArgSet &args, const char *argname, bool dflt=false)
|
||||
{
|
||||
return get_arg_bool_opt(args.kw.value(argname), argname, dflt);
|
||||
}
|
||||
|
||||
} // namespace mom
|
||||
|
||||
#endif /* MOO_SCRIPT_CLASSES_UTIL_H */
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
using namespace mom;
|
||||
|
||||
void mom::emit_signal(Object &obj, const char *name, const ArgArray &args, Accumulator *acc) throw()
|
||||
void mom::emit_signal(Object &obj, const char *name, const ArgList &args, Accumulator *acc) throw()
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -37,7 +37,7 @@ mom_signal_editor_save_before (MooEdit *doc, GFile *file, const char *encoding)
|
||||
if (!editor.has_callbacks("document-save-before"))
|
||||
return false;
|
||||
|
||||
ArgArray args;
|
||||
ArgList args;
|
||||
args.append(HObject(*Document::wrap(doc)));
|
||||
args.append(String(path));
|
||||
args.append(String(encoding));
|
||||
@ -60,7 +60,7 @@ mom_signal_editor_save_after (MooEdit *doc)
|
||||
if (!editor.has_callbacks("document-save-after"))
|
||||
return;
|
||||
|
||||
ArgArray args;
|
||||
ArgList args;
|
||||
args.append(HObject(*Document::wrap(doc)));
|
||||
emit_signal(editor, "document-save-after", args);
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ private:
|
||||
bool m_stop;
|
||||
};
|
||||
|
||||
void emit_signal(Object &obj, const char *name, const ArgArray &args, Accumulator *acc = 0) throw();
|
||||
void emit_signal(Object &obj, const char *name, const ArgList &args, Accumulator *acc = 0) throw();
|
||||
|
||||
} // namespace mom
|
||||
|
||||
|
@ -104,7 +104,7 @@ static Variant get_arg_variant(lua_State *L, int narg);
|
||||
|
||||
static Variant convert_table_to_variant(lua_State *L, int narg)
|
||||
{
|
||||
ArgArray ar;
|
||||
ArgList list;
|
||||
VariantDict dic;
|
||||
|
||||
size_t len = lua_objlen(L, narg);
|
||||
@ -116,7 +116,7 @@ static Variant convert_table_to_variant(lua_State *L, int narg)
|
||||
|
||||
bool int_idx = lua_isnumber(L, -2);
|
||||
|
||||
if ((int_idx && !dic.empty()) || (!int_idx && !ar.empty()))
|
||||
if ((int_idx && !dic.empty()) || (!int_idx && !list.empty()))
|
||||
luaL_argerror(L, narg, "either table with string keys or an array expected");
|
||||
|
||||
if (int_idx)
|
||||
@ -125,10 +125,10 @@ static Variant convert_table_to_variant(lua_State *L, int narg)
|
||||
if (idx <= 0 || idx > (int) len)
|
||||
luaL_argerror(L, narg, "either table with string keys or an array expected");
|
||||
|
||||
if (ar.size() < idx)
|
||||
ar.resize(idx);
|
||||
if (list.size() < idx)
|
||||
list.resize(idx);
|
||||
|
||||
ar[idx - 1] = v;
|
||||
list[idx - 1] = v;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -144,7 +144,7 @@ static Variant convert_table_to_variant(lua_State *L, int narg)
|
||||
if (!dic.empty())
|
||||
return dic;
|
||||
else
|
||||
return ar;
|
||||
return list;
|
||||
}
|
||||
|
||||
static Variant get_arg_variant(lua_State *L, int narg)
|
||||
@ -199,7 +199,7 @@ static void check_result(lua_State *L, Result r)
|
||||
|
||||
static void push_variant(lua_State *L, const Variant &v);
|
||||
|
||||
static void push_args_array(lua_State *L, const ArgArray &args)
|
||||
static void push_args_array(lua_State *L, const ArgList &args)
|
||||
{
|
||||
for (int i = 0, c = args.size(); i < c; ++i)
|
||||
push_variant(L, args[i]);
|
||||
@ -222,12 +222,12 @@ static int cfunc_call_named_method(lua_State *L)
|
||||
if (harg.id() != self.id())
|
||||
first_arg = 1;
|
||||
|
||||
ArgArray args;
|
||||
ArgList args;
|
||||
for (int i = first_arg; i <= lua_gettop(L); ++i)
|
||||
args.append(get_arg_variant(L, i));
|
||||
|
||||
Variant v;
|
||||
Result r = Script::call_method(self, meth, args, v);
|
||||
Result r = Script::call_method(self, meth, ArgSet(args), v);
|
||||
check_result(L, r);
|
||||
|
||||
if (v.vt() != VtVoid)
|
||||
@ -331,7 +331,8 @@ static void push_variant(lua_State *L, const Variant &v)
|
||||
case VtObject:
|
||||
push_object(L, v.value<VtObject>());
|
||||
return;
|
||||
case VtArgs:
|
||||
case VtArgList:
|
||||
case VtArgDict:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -373,12 +374,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
Variant run(const ArgArray &args)
|
||||
Variant run(const ArgList &args)
|
||||
{
|
||||
this->retval.reset();
|
||||
this->args = args;
|
||||
do_run(L, this);
|
||||
this->args = ArgArray();
|
||||
this->args = ArgList();
|
||||
Variant retval = this->retval;
|
||||
this->retval.reset();
|
||||
return retval;
|
||||
@ -396,7 +397,7 @@ public:
|
||||
lua_State *L;
|
||||
gulong id;
|
||||
Variant retval;
|
||||
ArgArray args;
|
||||
ArgList args;
|
||||
};
|
||||
|
||||
static int cfunc_connect(lua_State *L)
|
||||
|
@ -15,7 +15,8 @@ enum VariantType
|
||||
VtDouble,
|
||||
VtString,
|
||||
VtArray,
|
||||
VtArgs,
|
||||
VtArgList,
|
||||
VtArgDict,
|
||||
VtDict,
|
||||
VtObject,
|
||||
};
|
||||
@ -28,11 +29,11 @@ public:
|
||||
VariantArray() : moo::Vector<Variant>() {}
|
||||
};
|
||||
|
||||
class ArgArray : public VariantArray
|
||||
class ArgList : public VariantArray
|
||||
{
|
||||
public:
|
||||
ArgArray() {}
|
||||
ArgArray(const VariantArray &ar) : VariantArray(ar) {}
|
||||
ArgList() {}
|
||||
ArgList(const VariantArray &ar) : VariantArray(ar) {}
|
||||
};
|
||||
|
||||
class VariantDict : public moo::Dict<String, Variant>
|
||||
@ -41,6 +42,13 @@ public:
|
||||
VariantDict() : moo::Dict<String, Variant>() {}
|
||||
};
|
||||
|
||||
class ArgDict : public VariantDict
|
||||
{
|
||||
public:
|
||||
ArgDict() {}
|
||||
ArgDict(const VariantDict &dic) : VariantDict(dic) {}
|
||||
};
|
||||
|
||||
union VariantData
|
||||
{
|
||||
char p[1];
|
||||
@ -141,7 +149,8 @@ MOM_DEFINE_VT_HELPER(VtDouble, double)
|
||||
MOM_DEFINE_VT_HELPER(VtObject, HObject)
|
||||
MOM_DEFINE_VT_HELPER(VtString, String)
|
||||
MOM_DEFINE_VT_HELPER(VtArray, VariantArray)
|
||||
MOM_DEFINE_VT_HELPER(VtArgs, ArgArray)
|
||||
MOM_DEFINE_VT_HELPER(VtArgList, ArgList)
|
||||
MOM_DEFINE_VT_HELPER(VtArgDict, ArgDict)
|
||||
MOM_DEFINE_VT_HELPER(VtDict, VariantDict)
|
||||
|
||||
#undef MOM_DEFINE_VT_HELPER
|
||||
@ -164,7 +173,8 @@ inline void destroyTyped(VariantData &data)
|
||||
MOM_VT_CASE(VtObject, what); \
|
||||
MOM_VT_CASE(VtString, what); \
|
||||
MOM_VT_CASE(VtArray, what); \
|
||||
MOM_VT_CASE(VtArgs, what); \
|
||||
MOM_VT_CASE(VtArgList, what); \
|
||||
MOM_VT_CASE(VtArgDict, what); \
|
||||
MOM_VT_CASE(VtDict, what);
|
||||
|
||||
NOTHROW inline void destroy(VariantType vt, VariantData &data)
|
||||
|
@ -21,7 +21,7 @@ void Object::_InitMetaObjectFull(MetaObject &meta)
|
||||
InitMetaObject(meta);
|
||||
}
|
||||
|
||||
Variant Object::call_method(const String &name, const ArgArray &args)
|
||||
Variant Object::call_method(const String &name, const ArgSet &args)
|
||||
{
|
||||
moo::SharedPtr<Method> meth = m_meta.lookup_method(name);
|
||||
if (!meth)
|
||||
@ -124,7 +124,7 @@ HObject Script::get_app_obj()
|
||||
}
|
||||
}
|
||||
|
||||
Result Script::call_method(HObject h, const String &meth, const ArgArray &args, Variant &ret)
|
||||
Result Script::call_method(HObject h, const String &meth, const ArgSet &args, Variant &ret)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -12,7 +12,7 @@ class Object;
|
||||
class Method : public moo::RefCounted<Method>
|
||||
{
|
||||
public:
|
||||
virtual Variant call (Object &obj, const ArgArray &args) = 0;
|
||||
virtual Variant call(Object &obj, const ArgSet &args) = 0;
|
||||
};
|
||||
|
||||
class Signal : public moo::RefCounted<Signal>
|
||||
@ -38,19 +38,19 @@ public:
|
||||
moo::SharedPtr<Signal> lookup_signal(const String &sig) const NOTHROW { return m_signals.value(sig); }
|
||||
|
||||
template<typename TObject>
|
||||
void add_method(const String &meth, Variant (TObject::*impl)(const ArgArray &args))
|
||||
void add_method(const String &meth, Variant (TObject::*impl)(const ArgSet &args))
|
||||
{
|
||||
class MethodImpl : public Method
|
||||
{
|
||||
public:
|
||||
typedef Variant (TObject::*CallFunc)(const ArgArray &args);
|
||||
typedef Variant (TObject::*CallFunc)(const ArgSet &args);
|
||||
|
||||
MethodImpl(CallFunc impl)
|
||||
: m_impl(impl)
|
||||
{
|
||||
}
|
||||
|
||||
Variant call(Object &obj, const ArgArray &args)
|
||||
Variant call(Object &obj, const ArgSet &args)
|
||||
{
|
||||
TObject &tobj = static_cast<TObject&>(obj);
|
||||
return (tobj.*m_impl)(args);
|
||||
@ -97,7 +97,7 @@ protected: \
|
||||
class Object : public moo::RefCounted<Object>
|
||||
{
|
||||
public:
|
||||
Variant call_method(const String &meth, const ArgArray &args);
|
||||
Variant call_method(const String &meth, const ArgSet &args);
|
||||
|
||||
gulong connect_callback(const String &name, moo::SharedPtr<Callback> cb);
|
||||
void disconnect_callback(gulong id);
|
||||
|
@ -2,6 +2,8 @@
|
||||
<class name='Application' singleton='1'>
|
||||
<method name='editor' retval='Editor'/>
|
||||
<method name='quit'/>
|
||||
|
||||
<method name='dialog' retval='variant' kwargs='1'/>
|
||||
</class>
|
||||
|
||||
<class name='Editor' singleton='1'>
|
||||
|
@ -6,8 +6,6 @@ import tempfile
|
||||
|
||||
import mooscriptparser as parser
|
||||
|
||||
marshals = set()
|
||||
|
||||
tmpl_decl_file_start = """\
|
||||
#ifndef MOO_SCRIPT_CLASSES_GENERATED_H
|
||||
#define MOO_SCRIPT_CLASSES_GENERATED_H
|
||||
@ -25,10 +23,6 @@ tmpl_decl_file_end = """\
|
||||
#endif /* MOO_SCRIPT_CLASSES_GENERATED_H */
|
||||
"""
|
||||
|
||||
# tmpl_decl_get_type_func = """\
|
||||
# GType mom_%(class_name)s_get_type (void) G_GNUC_CONST;
|
||||
# """
|
||||
|
||||
tmpl_decl_forward_cls = """\
|
||||
class %(ClassName)s;
|
||||
"""
|
||||
@ -83,11 +77,8 @@ def make_method_dict(meth, cls):
|
||||
dic['signal_name'] = '-'.join(comps)
|
||||
return dic
|
||||
|
||||
# tmpl_method_impl_decl = """\
|
||||
# %(retval)smom_%(class_name)s_%(method_name)s (Mom%(ClassName)s *self%(args)s);
|
||||
# """
|
||||
tmpl_gen_method_decl = """\
|
||||
Variant _%(method_name)s(const ArgArray &args);
|
||||
Variant %(method_name)s__imp__(const ArgSet &args);
|
||||
"""
|
||||
tmpl_method_decl = """\
|
||||
%(retval)s%(method_name)s(%(args)s);
|
||||
@ -107,7 +98,8 @@ def format_param_decl(p):
|
||||
'list': 'const VariantArray &',
|
||||
'int': 'gint64 ',
|
||||
'index': 'gint64 ',
|
||||
'args': 'const ArgArray &',
|
||||
'arglist': 'const ArgList &',
|
||||
'argset': 'const ArgSet &',
|
||||
}
|
||||
return basic_names[p.type.name] + p.name
|
||||
|
||||
@ -204,18 +196,22 @@ FunctionCallInfo current_func()
|
||||
if (!func_calls.empty())
|
||||
return func_calls[func_calls.size() - 1];
|
||||
else
|
||||
return FunctionCallInfo("<no function>");
|
||||
moo_return_val_if_reached(FunctionCallInfo("<no function>"));
|
||||
}
|
||||
|
||||
static void push_function_call(const char *name)
|
||||
class PushFunctionCall
|
||||
{
|
||||
func_calls.append(FunctionCallInfo(name));
|
||||
}
|
||||
public:
|
||||
explicit PushFunctionCall(const char *name)
|
||||
{
|
||||
func_calls.append(FunctionCallInfo(name));
|
||||
}
|
||||
|
||||
static void pop_function_call()
|
||||
{
|
||||
func_calls.pop_back();
|
||||
}
|
||||
~PushFunctionCall()
|
||||
{
|
||||
func_calls.pop_back();
|
||||
}
|
||||
};
|
||||
|
||||
"""
|
||||
|
||||
@ -236,127 +232,56 @@ tmpl_impl_class_init_end = """\
|
||||
}
|
||||
"""
|
||||
|
||||
# tmpl_impl_assign_meth = """\
|
||||
# klass->%(method_name)s = mom_%(class_name)s_%(method_name)s;
|
||||
# """
|
||||
|
||||
tmpl_impl_method = """\
|
||||
meta.add_method("%(method_name)s", &%(ClassName)s::_%(method_name)s);
|
||||
meta.add_method("%(method_name)s", &%(ClassName)s::%(method_name)s__imp__);
|
||||
"""
|
||||
|
||||
tmpl_impl_signal = """\
|
||||
meta.add_signal("%(signal_name)s");
|
||||
"""
|
||||
|
||||
def format_mom_type(retval):
|
||||
if retval is None:
|
||||
return 'MOM_TYPE_NONE'
|
||||
elif isinstance(retval.type, parser.Class):
|
||||
comps = split_camel_case_name(retval.type.name)
|
||||
return '_'.join(['MOM', 'TYPE'] + [s.upper() for s in comps])
|
||||
else:
|
||||
basic_types = {
|
||||
'bool': 'MOM_TYPE_BOOL',
|
||||
'string': 'MOM_TYPE_STRING',
|
||||
'variant': 'MOM_TYPE_VARIANT',
|
||||
'list': 'MOM_TYPE_LIST',
|
||||
'args': 'MOM_TYPE_ARGS',
|
||||
'int': 'MOM_TYPE_INT',
|
||||
'index': 'MOM_TYPE_INDEX',
|
||||
'base1': 'MOM_TYPE_BASE1',
|
||||
}
|
||||
return basic_types[retval.type.name]
|
||||
|
||||
def format_marshal_type(p):
|
||||
if p is None:
|
||||
return 'VOID'
|
||||
elif isinstance(p.type, parser.Class):
|
||||
return 'OBJECT'
|
||||
else:
|
||||
basic_types = {
|
||||
'bool': 'BOOL',
|
||||
'string': 'STRING',
|
||||
'variant': 'BOXED',
|
||||
'list': 'BOXED',
|
||||
'int': 'INT64',
|
||||
'index': 'UINT64',
|
||||
'args': 'BOXED',
|
||||
}
|
||||
return basic_types[p.type.name]
|
||||
|
||||
def format_marshal(meth):
|
||||
if meth.params:
|
||||
arg_types = [format_marshal_type(p) for p in meth.params]
|
||||
else:
|
||||
arg_types = ['VOID']
|
||||
m = 'mom_marshal_%s__%s' % (format_marshal_type(meth.retval), '_'.join(arg_types))
|
||||
global marshals
|
||||
marshals.add(m)
|
||||
return m
|
||||
|
||||
def write_class_init(cls, out):
|
||||
dic = make_class_dict(cls)
|
||||
out.write(tmpl_impl_class_init_start % dic)
|
||||
|
||||
# for meth in cls.methods.values():
|
||||
# meth_dic = make_method_dict(meth, cls)
|
||||
# out.write(tmpl_impl_assign_meth % meth_dic)
|
||||
|
||||
for meth in cls.methods.values():
|
||||
meth_dic = make_method_dict(meth, cls)
|
||||
meth_dic['accumulator'] = 'NULL'
|
||||
meth_dic['marshal'] = format_marshal(meth)
|
||||
meth_dic['TYPE_RET'] = format_mom_type(meth.retval)
|
||||
meth_dic['n_params'] = len(meth.params)
|
||||
out.write(tmpl_impl_method % meth_dic)
|
||||
|
||||
for meth in cls.signals.values():
|
||||
meth_dic = make_method_dict(meth, cls)
|
||||
meth_dic['accumulator'] = 'NULL'
|
||||
meth_dic['marshal'] = format_marshal(meth)
|
||||
meth_dic['TYPE_RET'] = format_mom_type(meth.retval)
|
||||
meth_dic['n_params'] = len(meth.params)
|
||||
out.write(tmpl_impl_signal % meth_dic)
|
||||
# if meth.params:
|
||||
# for p in meth.params:
|
||||
# mtype = format_mom_type(p)
|
||||
# out.write(tmpl_impl_method_param % (mtype,))
|
||||
# out.write(');\n')
|
||||
|
||||
out.write(tmpl_impl_class_init_end % dic)
|
||||
|
||||
# def write_object_init(cls, out):
|
||||
# dic = make_class_dict(cls)
|
||||
# out.write(tmpl_impl_object_init % dic)
|
||||
|
||||
tmpl_method_impl_start = """\
|
||||
Variant %(ClassName)s::_%(method_name)s(const ArgArray &args)
|
||||
Variant %(ClassName)s::%(method_name)s__imp__(const ArgSet &args)
|
||||
{
|
||||
push_function_call("%(ClassName)s::%(method_name)s");
|
||||
try {
|
||||
PushFunctionCall pfc__("%(ClassName)s::%(method_name)s");
|
||||
"""
|
||||
tmpl_method_impl_end = """\
|
||||
} catch(...) {
|
||||
pop_function_call();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
"""
|
||||
tmpl_check_no_args = """\
|
||||
if (args.size() != 0)
|
||||
if (!args.pos.empty() || !args.kw.empty())
|
||||
Error::raisef("in function %s, no arguments expected",
|
||||
(const char*) current_func().name);
|
||||
(const char*) current_func().name);
|
||||
"""
|
||||
tmpl_check_no_kwargs = """\
|
||||
if (!args.kw.empty())
|
||||
Error::raisef("in function %s, no keyword arguments expected",
|
||||
(const char*) current_func().name);
|
||||
"""
|
||||
|
||||
tmpl_get_obj_arg = """\
|
||||
if (args.size() <= %(iarg)d)
|
||||
if (args.pos.size() <= %(iarg)d)
|
||||
Error::raisef("in function %%s, argument '%(argname)s' missing",
|
||||
(const char*) current_func().name);
|
||||
%(type)s &%(arg)s = get_object_arg<%(type)s>(args[%(iarg)d], "%(argname)s");
|
||||
(const char*) current_func().name);
|
||||
%(type)s &%(arg)s = get_object_arg<%(type)s>(args.pos[%(iarg)d], "%(argname)s");
|
||||
"""
|
||||
|
||||
tmpl_get_obj_arg_opt = """\
|
||||
%(type)s *%(arg)s = get_object_arg_opt<%(type)s>(args.size() > %(iarg)d ? args[%(iarg)d] : Variant(), "%(argname)s");
|
||||
%(type)s *%(arg)s = get_object_arg_opt<%(type)s>(args.pos.size() > %(iarg)d ? args.pos[%(iarg)d] : Variant(), "%(argname)s");
|
||||
"""
|
||||
|
||||
def write_check_arg_object(meth, p, i, out):
|
||||
@ -367,14 +292,14 @@ def write_check_arg_object(meth, p, i, out):
|
||||
out.write(tmpl_get_obj_arg % dic)
|
||||
|
||||
tmpl_get_arg = """\
|
||||
if (args.size() <= %(iarg)d)
|
||||
if (args.pos.size() <= %(iarg)d)
|
||||
Error::raisef("in function %%s, argument '%(argname)s' missing",
|
||||
(const char*) current_func().name);
|
||||
%(type)s %(arg)s = %(get_arg)s(args[%(iarg)d], "%(argname)s");
|
||||
%(type)s %(arg)s = %(get_arg)s(args.pos[%(iarg)d], "%(argname)s");
|
||||
"""
|
||||
|
||||
tmpl_get_arg_opt = """\
|
||||
%(type)s %(arg)s = %(get_arg)s_opt(args.size() > %(iarg)d ? args[%(iarg)d] : Variant(), "%(argname)s");
|
||||
%(type)s %(arg)s = %(get_arg)s_opt(args.pos.size() > %(iarg)d ? args.pos[%(iarg)d] : Variant(), "%(argname)s");
|
||||
"""
|
||||
|
||||
def write_check_arg(meth, p, i, out):
|
||||
@ -405,9 +330,12 @@ def write_check_arg(meth, p, i, out):
|
||||
def write_method_impl_check_args(meth, out):
|
||||
if not meth.params:
|
||||
out.write(tmpl_check_no_args)
|
||||
elif len(meth.params) == 1 and meth.params[0].type.name == 'args':
|
||||
elif meth.kwargs:
|
||||
pass
|
||||
elif meth.varargs:
|
||||
out.write(tmpl_check_no_kwargs)
|
||||
else:
|
||||
out.write(tmpl_check_no_kwargs)
|
||||
i = 0
|
||||
for p in meth.params:
|
||||
write_check_arg(meth, p, i, out)
|
||||
@ -436,8 +364,10 @@ def write_method_impl_call_func(meth, out):
|
||||
write_wrap_retval(meth, out)
|
||||
out.write(meth.name + '(')
|
||||
if meth.params:
|
||||
if len(meth.params) == 1 and meth.params[0].type.name == 'args':
|
||||
if meth.kwargs:
|
||||
out.write('args')
|
||||
elif meth.varargs:
|
||||
out.write('args.pos')
|
||||
else:
|
||||
out.write(', '.join(['arg%d' % (i,) for i in range(len(meth.params))]))
|
||||
out.write(')')
|
||||
@ -475,13 +405,6 @@ def write_module_impl(out, mod):
|
||||
|
||||
out.write(tmpl_impl_file_end)
|
||||
|
||||
# def write_marshals(out):
|
||||
# global marshals
|
||||
# print >> out, "namespace mom {"
|
||||
# for m in sorted(marshals):
|
||||
# print >> out, 'static Variant %s(Object *self, const ArgArray &args);' % (m,)
|
||||
# print >> out, "} // namespace mom"
|
||||
|
||||
def generate_file(filename, gen_func, *args):
|
||||
tmp = tempfile.NamedTemporaryFile(dir=os.path.dirname(filename), delete=False)
|
||||
try:
|
||||
@ -497,7 +420,6 @@ def do_generate(input_file, decl_file, impl_file):
|
||||
mod = p.parse(input_file)
|
||||
generate_file(decl_file, write_module_decl, mod)
|
||||
generate_file(impl_file, write_module_impl, mod)
|
||||
# generate_file(marshals_file, write_marshals)
|
||||
|
||||
if __name__ == '__main__':
|
||||
from optparse import OptionParser
|
||||
|
@ -46,6 +46,8 @@ class _MethodBase(object):
|
||||
self.name = name
|
||||
self.params = []
|
||||
self.retval = None
|
||||
self.varargs = False
|
||||
self.kwargs = False
|
||||
|
||||
class Method(_MethodBase):
|
||||
def __init__(self, name):
|
||||
@ -111,7 +113,7 @@ class Parser(object):
|
||||
raise RuntimeError("oops: '%s'" % (typ,))
|
||||
|
||||
def __check_types(self, mod):
|
||||
for t in ('bool', 'string', 'variant', 'list', 'int', 'index', 'args'):
|
||||
for t in ('bool', 'string', 'variant', 'list', 'int', 'index', 'arglist', 'argset'):
|
||||
mod.types[t] = BasicType(t)
|
||||
for name in mod.classes:
|
||||
cls = mod.classes[name]
|
||||
@ -156,7 +158,15 @@ class Parser(object):
|
||||
if elm.get('varargs') is not None:
|
||||
va = parse_bool(elm.get('varargs'))
|
||||
if va:
|
||||
meth.params.append(Param('args', 'args'))
|
||||
meth.varargs = True
|
||||
meth.params.append(Param('args', 'arglist'))
|
||||
else:
|
||||
raise RuntimeError('oops')
|
||||
elif elm.get('kwargs') is not None:
|
||||
va = parse_bool(elm.get('kwargs'))
|
||||
if va:
|
||||
meth.kwargs = True
|
||||
meth.params.append(Param('args', 'argset'))
|
||||
else:
|
||||
raise RuntimeError('oops')
|
||||
elif elm.get('param-name') is not None:
|
||||
|
@ -72,9 +72,10 @@ class Method(object):
|
||||
self.__obj = obj
|
||||
self.__meth = meth
|
||||
|
||||
def __call__(self, *args):
|
||||
def __call__(self, *args, **kwargs):
|
||||
args_v = VariantArray(args)
|
||||
ret = eval(_medit_raw.call_method(self.__obj._id(), self.__meth, args_v.p))
|
||||
kwargs_v = VariantDict(kwargs)
|
||||
ret = eval(_medit_raw.call_method(self.__obj._id(), self.__meth, args_v.p, kwargs_v.p))
|
||||
if isinstance(ret, Exception):
|
||||
raise ret
|
||||
else:
|
||||
|
@ -148,9 +148,9 @@ encode_variant (const Variant &val, GString *str)
|
||||
case VtArray:
|
||||
encode_list (val.value<VtArray>(), str);
|
||||
break;
|
||||
case VtArgs:
|
||||
encode_list (val.value<VtArgs>(), str);
|
||||
break;
|
||||
// case VtArgList:
|
||||
// encode_list (val.value<VtArgList>(), str);
|
||||
// break;
|
||||
case VtDict:
|
||||
encode_dict (val.value<VtDict>(), str);
|
||||
break;
|
||||
@ -184,7 +184,7 @@ encode_list (const VariantArray &list, GString *str)
|
||||
}
|
||||
|
||||
static void
|
||||
encode_args (const ArgArray &args, GString *str)
|
||||
encode_args (const ArgList &args, GString *str)
|
||||
{
|
||||
encode_list_elms (args, str);
|
||||
}
|
||||
@ -331,11 +331,16 @@ cfunc_push_retval (guint id, const Variant *value)
|
||||
moo_python_module.retvals[id] = *value;
|
||||
}
|
||||
|
||||
#define CFUNC_PROTO_call_method "ctypes.c_char_p, ctypes.c_uint, ctypes.c_char_p, ctypes.c_void_p"
|
||||
#define CFUNC_PROTO_call_method "ctypes.c_char_p, ctypes.c_uint, ctypes.c_char_p, ctypes.c_void_p, ctypes.c_void_p"
|
||||
static char *
|
||||
cfunc_call_method (guint obj_id, const char *method, const VariantArray *argsv)
|
||||
cfunc_call_method (guint obj_id, const char *method, const VariantArray *args_pos, const VariantDict *args_kw)
|
||||
{
|
||||
ArgArray args (argsv ? *argsv : VariantArray ());
|
||||
ArgSet args;
|
||||
if (args_pos)
|
||||
args.pos = *args_pos;
|
||||
if (args_kw)
|
||||
args.kw = *args_kw;
|
||||
|
||||
Variant ret;
|
||||
|
||||
moo_python_ref ();
|
||||
@ -352,7 +357,7 @@ struct MooPythonCallback : public Callback
|
||||
{
|
||||
gulong id;
|
||||
|
||||
Variant run(const ArgArray &args)
|
||||
Variant run(const ArgList &args)
|
||||
{
|
||||
guint retval_id = ++moo_python_module.last_retval_id;
|
||||
|
||||
@ -368,7 +373,7 @@ struct MooPythonCallback : public Callback
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
moo_message ("error in PyRun_SimpleString");
|
||||
// moo_message ("error in PyRun_SimpleString");
|
||||
return Variant();
|
||||
}
|
||||
else if (!moo_python_module.retvals.contains(retval_id))
|
||||
@ -545,7 +550,7 @@ moo_python_init_impl (void)
|
||||
|
||||
if (moo_python_module.pfn_PyRun_SimpleString (init_script->str) != 0)
|
||||
{
|
||||
moo_message ("error in PyRun_SimpleString");
|
||||
moo_critical ("error in PyRun_SimpleString");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -642,7 +647,7 @@ moo_python_run_string_full (const char *prefix,
|
||||
|
||||
if (moo_python_module.pfn_PyRun_SimpleString (script->str) != 0)
|
||||
{
|
||||
moo_message ("error in PyRun_SimpleString");
|
||||
// moo_message ("error in PyRun_SimpleString");
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user