Keyword arguments

This commit is contained in:
Yevgen Muntyan 2010-11-02 01:56:33 -07:00
parent 035c482c33
commit 4e0169a45b
14 changed files with 327 additions and 177 deletions

View File

@ -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;
};

View File

@ -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;

View File

@ -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 */

View File

@ -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);
}

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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
{

View File

@ -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);

View File

@ -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'>

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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;
}