[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-API] [Xen-devel] [PATCH 07 of 15] libxl: ocaml: support for KeyedUnion in the bindings generator
> # HG changeset patch > # User Ian Campbell <ijc@xxxxxxxxxxxxxx> # Date 1353432141 0 # Node ID > 0cf342afa9e6b506fad68346cb3a1207030372eb > # Parent f618acdeea1bf60b3b68da4062de018d8162fe8c > libxl: ocaml: support for KeyedUnion in the bindings generator. > > A KeyedUnion consists of two fields in the containing struct. First an enum > field ("e") used as a descriminator and second a union ("u") containing > potentially anonymous structs associated with each enum value. > > We map the anonymous structs to structs named after the descriminator > field ("e") and the specific enum values. We then declare an ocaml variant > type name e__union mapping each enum value to its associated struct. > > So given IDL: > > foo = Enumeration("foo", > (0, "BAR"), > (1, "BAZ"), > s = Struct("s", [ > ("u", KeyedUnion(none, foo, "blargle", [ > ("bar", Struct(...xxx...)), > ("baz", Struct(...yyy...)), > ])), > ]) > > We generate C: > > enum { FOO, BAR } foo; > struct s { > enum foo blargle; > union { > struct { ...xxx... } bar; > struct { ...yyy... } baz; > } u; > } > > and map this to ocaml > > type foo = BAR | BAZ; > > module s = Struct > > type blargle_bar = ...xxx...; > > type blargle_baz = ...yyy...; > > type blargle__union = Bar of blargle_bar | Baz of blargle_baz; > > type t = > { > blargle : blargle__union; > } > > These type names are OK because they are already within the namespace > associated with the struct "s". I think this is a useful representation of KeyedUnion types in ocaml. I'll play around a bit with this implementation. Cheers, Rob > If the struct assiated with bar is empty then we don't bother iwht > blargle_bar of "of blargle_bar". > > No actually change in the gnerated code since we don't generated any > KeyedUnions yet. > > The actual implementation was inspired by http://www.linux- > nantes.org/~fmonnier/ocaml/ocaml-wrapping-c.php#ref_constvrnt > > Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx> > > diff -r f618acdeea1b -r 0cf342afa9e6 tools/libxl/idl.py > --- a/tools/libxl/idl.py Tue Nov 20 17:22:21 2012 +0000 > +++ b/tools/libxl/idl.py Tue Nov 20 17:22:21 2012 +0000 > @@ -216,6 +216,9 @@ class Struct(Aggregate): > kwargs.setdefault('passby', PASS_BY_REFERENCE) > Aggregate.__init__(self, "struct", name, fields, **kwargs) > > + def has_fields(self): > + return len(self.fields) != 0 > + > class Union(Aggregate): > def __init__(self, name, fields, **kwargs): > # Generally speaking some intelligence is required to free a diff -r > f618acdeea1b -r 0cf342afa9e6 tools/ocaml/libs/xl/genwrap.py > --- a/tools/ocaml/libs/xl/genwrap.py Tue Nov 20 17:22:21 2012 +0000 > +++ b/tools/ocaml/libs/xl/genwrap.py Tue Nov 20 17:22:21 2012 +0000 > @@ -65,6 +65,8 @@ def ocaml_type_of(ty): > if not typename: > raise NotImplementedError("No typename for Builtin %s (%s)" % > (ty.typename, type(ty))) > return typename > + elif isinstance(ty,idl.KeyedUnion): > + return ty.union_name > elif isinstance(ty,idl.Aggregate): > return ty.rawname.capitalize() + ".t" > else: > @@ -76,8 +78,67 @@ def munge_name(name): > else: > return name > > -def ocaml_instance_of(type, name): > - return "%s : %s" % (munge_name(name), ocaml_type_of(type)) > +def ocaml_instance_of_field(f): > + if isinstance(f.type, idl.KeyedUnion): > + name = f.type.keyvar.name > + else: > + name = f.name > + return "%s : %s" % (munge_name(name), ocaml_type_of(f.type)) > + > +def gen_struct(ty): > + s = "" > + for f in ty.fields: > + if f.type.private: > + continue > + x = ocaml_instance_of_field(f) > + x = x.replace("\n", "\n\t\t") > + s += "\t\t" + x + ";\n" > + return s > + > +def gen_ocaml_keyedunions(ty, interface, indent, parent = None): > + s = "" > + > + if ty.rawname is not None: > + # Non-anonymous types need no special handling > + pass > + elif isinstance(ty, idl.KeyedUnion): > + if parent is None: > + nparent = ty.keyvar.name > + else: > + nparent = parent + "_" + ty.keyvar.name > + > + for f in ty.fields: > + if f.type is None: continue > + if f.type.rawname is not None: continue > + if isinstance(f.type, idl.Struct) and not f.type.has_fields(): > continue > + s += "\ntype %s_%s =\n" % (nparent,f.name) > + s += "{\n" > + s += gen_struct(f.type) > + s += "}\n" > + > + name = "%s__union" % ty.keyvar.name > + s += "\n" > + s += "type %s = " % name > + u = [] > + for f in ty.fields: > + if f.type is None: > + u.append("%s" % (f.name.capitalize())) > + elif isinstance(f.type, idl.Struct): > + if f.type.rawname is not None: > + u.append("%s of %s" % (f.name.capitalize(), > f.type.rawname.capitalize())) > + elif f.type.has_fields(): > + u.append("%s of %s_%s" % (f.name.capitalize(), nparent, > f.name)) > + else: > + u.append("%s" % (f.name.capitalize())) > + else: > + raise NotImplementedError("Cannot handle KeyedUnion > + fields which are not Structs") > + > + s += " | ".join(u) + "\n" > + ty.union_name = name > + > + if s == "": > + return None > + return s.replace("\n", "\n%s" % indent) > > def gen_ocaml_ml(ty, interface, indent=""): > > @@ -103,16 +164,17 @@ def gen_ocaml_ml(ty, interface, indent=" > s += "module %s : sig\n" % module_name > else: > s += "module %s = struct\n" % module_name > - s += "\ttype t =\n" > - s += "\t{\n" > - > + > + # Handle KeyedUnions... > for f in ty.fields: > - if f.type.private: > - continue > - x = ocaml_instance_of(f.type, f.name) > - x = x.replace("\n", "\n\t\t") > - s += "\t\t" + x + ";\n" > + ku = gen_ocaml_keyedunions(f.type, interface, "\t") > + if ku is not None: > + s += ku > + s += "\n" > > + s += "\ttype t =\n" > + s += "\t{\n" > + s += gen_struct(ty) > s += "\t}\n" > > if functions.has_key(ty.rawname): > @@ -164,12 +226,43 @@ def c_val(ty, c, o, indent="", parent = > n += 1 > s += " default: failwith_xl(\"cannot convert value to %s\", lg); > break;\n" % ty.typename > s += "}" > - elif isinstance(ty, idl.Aggregate) and (parent is None): > + elif isinstance(ty, idl.KeyedUnion): > + s += "{\n" > + s += "\tif(Is_long(%s)) {\n" % o > + n = 0 > + s += "\t\tswitch(Int_val(%s)) {\n" % o > + for f in ty.fields: > + if f.type is None or not f.type.has_fields(): > + s += "\t\t case %d: %s = %s; break;\n" % (n, > + parent + ty.keyvar.name, > + f.enumname) > + n += 1 > + s += "\t\t default: failwith_xl(\"variant handling bug %s%s > (long)\", > lg); break;\n" % (parent, ty.keyvar.name) > + s += "\t\t}\n" > + s += "\t} else {\n" > + s += "\t\t/* Is block... */\n" > + s += "\t\tswitch(Tag_val(%s)) {\n" % o > + n = 0 > + for f in ty.fields: > + if f.type is not None and f.type.has_fields(): > + if f.type.private: > + continue > + s += "\t\t case %d:\n" % (n) > + s += "\t\t %s = %s;\n" % (parent + ty.keyvar.name, > f.enumname) > + (nparent,fexpr) = ty.member(c, f, False) > + s += "%s" % c_val(f.type, fexpr, o, indent=indent+"\t\t > ") > + s += "break;\n" > + n += 1 > + s += "\t\t default: failwith_xl(\"variant handling bug %s%s > (block)\", > lg); break;\n" % (parent, ty.keyvar.name) > + s += "\t\t}\n" > + s += "\t}\n" > + s += "}" > + elif isinstance(ty, idl.Aggregate) and (parent is None or ty.rawname is > None): > n = 0 > for f in ty.fields: > if f.type.private: > continue > - (nparent,fexpr) = ty.member(c, f, parent is None) > + (nparent,fexpr) = ty.member(c, f, ty.rawname is not None) > s += "%s\n" % c_val(f.type, fexpr, "Field(%s, %d)" % (o,n), > parent=nparent) > n = n + 1 > else: > @@ -191,8 +284,8 @@ def gen_c_val(ty, indent=""): > s += "}\n" > > return s.replace("\n", "\n%s" % indent) > - > -def ocaml_Val(ty, o, c, indent="", parent = None): > + > +def ocaml_Val(ty, o, c, indent="", parent = None, struct_tag = None): > s = indent > if isinstance(ty,idl.UInt): > if ty.width in [8, 16]: > @@ -231,11 +324,39 @@ def ocaml_Val(ty, o, c, indent="", paren > n += 1 > s += " default: failwith_xl(\"cannot convert value from %s\", lg); > break;\n" % ty.typename > s += "}" > - elif isinstance(ty,idl.Aggregate) and (parent is None): > + elif isinstance(ty, idl.KeyedUnion): > + n = 0 > + s += "switch(%s) {\n" % (parent + ty.keyvar.name) > + for f in ty.fields: > + s += "\t case %s:\n" % f.enumname > + if f.type is None: > + s += "\t /* %d: None */\n" % n > + s += "\t %s = Val_long(%d);\n" % (o,n) > + elif not f.type.has_fields(): > + s += "\t /* %d: Long */\n" % n > + s += "\t %s = Val_long(%d);\n" % (o,n) > + else: > + s += "\t /* %d: Block */\n" % n > + (nparent,fexpr) = ty.member(c, f, parent is None) > + s += ocaml_Val(f.type, o, fexpr, struct_tag = n, indent="\t > ", > parent=nparent) > + s += "\n" > + #s += "\t %s = caml_alloc(%d,%d);\n" % > (o,len(f.type.fields),n) > + s += "\t break;\n" > + n += 1 > + s += "\t default: failwith_xl(\"cannot convert value from %s\", > lg); > break;\n" % ty.typename > + s += "\t}" > + elif isinstance(ty,idl.Aggregate) and (parent is None or ty.rawname is > None): > s += "{\n" > - s += "\tvalue %s_field;\n" % ty.rawname > + if ty.rawname is None: > + fn = "anon_field" > + else: > + fn = "%s_field" % ty.rawname > + s += "\tvalue %s;\n" % fn > s += "\n" > - s += "\t%s = caml_alloc_tuple(%d);\n" % (o, len(ty.fields)) > + if struct_tag is not None: > + s += "\t%s = caml_alloc(%d,%d);\n" % (o, len(ty.fields), > struct_tag) > + else: > + s += "\t%s = caml_alloc_tuple(%d);\n" % (o, len(ty.fields)) > > n = 0 > for f in ty.fields: > @@ -245,8 +366,8 @@ def ocaml_Val(ty, o, c, indent="", paren > (nparent,fexpr) = ty.member(c, f, parent is None) > > s += "\n" > - s += "\t%s\n" % ocaml_Val(f.type, "%s_field" % ty.rawname, > ty.pass_arg(fexpr, c), parent=nparent) > - s += "\tStore_field(%s, %d, %s);\n" % (o, n, "%s_field" % > ty.rawname) > + s += "\t%s\n" % ocaml_Val(f.type, fn, ty.pass_arg(fexpr, c), > parent=nparent) > + s += "\tStore_field(%s, %d, %s);\n" % (o, n, fn) > n = n + 1 > s += "}" > else: > > _______________________________________________ > Xen-devel mailing list > Xen-devel@xxxxxxxxxxxxx > http://lists.xen.org/xen-devel _______________________________________________ Xen-api mailing list Xen-api@xxxxxxxxxxxxx http://lists.xen.org/cgi-bin/mailman/listinfo/xen-api
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |