* Generation of Java code from OCaml @ 2009-09-23 18:15 Mykola Stryebkov 2009-09-23 19:57 ` [Caml-list] " Richard Jones 0 siblings, 1 reply; 12+ messages in thread From: Mykola Stryebkov @ 2009-09-23 18:15 UTC (permalink / raw) To: caml-list Hi, I need to generate arbitrary text (more specifically, Java code) from Ocaml structures, pretty similar to how json-static lib generates ocaml code from ocaml structures. Which approach would you recommend? Is it possible to use ocamlp4 for it? -- Mykola Stryebkov Blog: http://mykola.org/blog/ Public key: http://mykola.org/pubkey.txt fpr: 0226 54EE C1FF 8636 36EF 2AC9 BCE9 CFC7 9CF4 6747 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Generation of Java code from OCaml 2009-09-23 18:15 Generation of Java code from OCaml Mykola Stryebkov @ 2009-09-23 19:57 ` Richard Jones 2009-09-23 22:54 ` Mykola Stryebkov 0 siblings, 1 reply; 12+ messages in thread From: Richard Jones @ 2009-09-23 19:57 UTC (permalink / raw) To: Mykola Stryebkov; +Cc: caml-list On Wed, Sep 23, 2009 at 09:15:08PM +0300, Mykola Stryebkov wrote: > I need to generate arbitrary text (more specifically, Java code) from > Ocaml structures, pretty similar to how json-static lib generates > ocaml code from ocaml structures. > > Which approach would you recommend? > Is it possible to use ocamlp4 for it? Do you want to generate valid Java code (or an AST) or just string bits of text together? FWIW we generate 100's of thousands of lines of C, Java and other languages using OCaml in libguestfs (by stringing bits of text together): http://git.et.redhat.com/?p=libguestfs.git;a=blob;f=src/generator.ml;hb=HEAD Rich. -- Richard Jones Red Hat ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Generation of Java code from OCaml 2009-09-23 19:57 ` [Caml-list] " Richard Jones @ 2009-09-23 22:54 ` Mykola Stryebkov 2009-09-24 8:03 ` David Allsopp 0 siblings, 1 reply; 12+ messages in thread From: Mykola Stryebkov @ 2009-09-23 22:54 UTC (permalink / raw) To: Richard Jones; +Cc: caml-list Hi, Richard. On 23 Вер 2009, at 22:57, Richard Jones wrote: > On Wed, Sep 23, 2009 at 09:15:08PM +0300, Mykola Stryebkov wrote: >> I need to generate arbitrary text (more specifically, Java code) from >> Ocaml structures, pretty similar to how json-static lib generates >> ocaml code from ocaml structures. >> >> Which approach would you recommend? >> Is it possible to use ocamlp4 for it? > > Do you want to generate valid Java code (or an AST) or just string > bits of text together? I'm going to use stringing bits of text together. But text generating is not an issue here. The issue is how to make this stringing driven by description of ocaml records. I have few hundreds of types. For each ocaml type I want to generate corresponding Java class with function (constructor) that initialize an object of this class from json string. E.g.: type json create_order_response = { order_id : int; order_code : string; order_price : int; ... } ... must be translated in something like: public class CreateOrderResponse extends ... implements ... { private int id = 0; private String code = ""; private int price = 0; ... public CreateOrderResponse(String json) { ... } }; P.S.: I'm using json-static library and its preprocessor module (http://martin.jambon.free.fr/json-static.html) to automatically generate functions, used to convert records (marked by "json" keyword) to strings in json format and vice versa. -- Mykola Stryebkov Blog: http://mykola.org/blog/ Public key: http://mykola.org/pubkey.txt fpr: 0226 54EE C1FF 8636 36EF 2AC9 BCE9 CFC7 9CF4 6747 ^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: [Caml-list] Generation of Java code from OCaml 2009-09-23 22:54 ` Mykola Stryebkov @ 2009-09-24 8:03 ` David Allsopp 2009-09-24 9:45 ` blue storm 0 siblings, 1 reply; 12+ messages in thread From: David Allsopp @ 2009-09-24 8:03 UTC (permalink / raw) To: caml-list Mykola Stryebkov wrote: > Hi, Richard. > > On 23 Вер 2009, at 22:57, Richard Jones wrote: <snip> > I'm going to use stringing bits of text together. But text generating > is not an issue here. The issue is how to make this stringing driven by > description of ocaml records. camlp4 would be the neatest, most stable way of doing this - as it sounds so similar in operation (if not function) to json-static, why not use its code as a reference/starting point? The alternative if you're happier with text processing and want to avoid the learning-curve for camlp4 would be to parse the output of `ocamlc -i` which is, in syntactic terms, canonical (where a source file is not) David ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Generation of Java code from OCaml 2009-09-24 8:03 ` David Allsopp @ 2009-09-24 9:45 ` blue storm 2009-09-24 11:18 ` Martin Jambon 0 siblings, 1 reply; 12+ messages in thread From: blue storm @ 2009-09-24 9:45 UTC (permalink / raw) To: Mykola Stryebkov, David Allsopp; +Cc: caml-list In case it helps, below is a basic patch against json-static (SVN trunk, 3.10 version). On your example it produces the following code : let javadef_of_create_order_response = "public class Create_order_response {\n\tprivate int order_id;\n\tprivate String order_code;\n\tprivate int order_price;\n\tpublic Create_order_response { ... }\n}" Wich, printed to sdout, gives the following output : public class Create_order_response { private int order_id; private String order_code; private int order_price; public Create_order_response { ... } } I choosed to generate the Java code inside an ocaml string declared inside the program to keep coherency with the other json code generators, but if you want you could easily output the java code to a separate file, and that would remove some of the string escaping in play. --- json-static/pa_json_static.ml.310 2009-09-24 11:40:28.000000000 +0200 +++ json-static-new/pa_json_static.ml.310 2009-09-24 11:39:52.000000000 +0200 @@ -1,3 +1,4 @@ +# 1 "pa_json_static.ml.310" (* Conversion between OCaml types and JSON types as provided by the json-wheel library. @@ -532,6 +533,39 @@ <:str_item< value rec $defs$ >> +let make_javadef _loc l = + let rec print name (_loc, l) = match l with + | Record r -> + let class_name = String.capitalize name in (* TODO : real java naming conventions *) + Printf.sprintf + "public class %s {\\n\ + \\t%s;\\n\ + \\tpublic %s { ... }\\n\ + }" (* TODO : real constructor body *) + class_name + (String.concat ";\\n\\t" (List.map print_field r)) + class_name + | _ -> Loc.raise _loc + (Failure "javadef patch draft : only records are supported") + and print_field f = + Printf.sprintf "private %s %s" + (print_type f.field_type) + f.field_caml_name + and print_type (_loc, t) = match t with + | String -> "String" + | Bool -> "bool" + | Int -> "int" + | Float -> "double" + | _ -> Loc.raise _loc + (Failure "javadef patch draft : only base types are supported") in + let defs = + List.fold_right + (fun ((_loc, name), x) acc -> + let fname = "javadef_of_" ^ name in + <:binding< $lid:fname$ = $str:print name x.def$ and $acc$ >>) + l <:binding<>> in + <:str_item< value $defs$ >> + let expand_typedefs _loc l = check_unique (fun (name, _) -> name) l; let names = @@ -541,7 +575,8 @@ let typedef = make_typedef _loc names l in let ofjson = make_ofjson _loc l in let tojson = make_tojson _loc l in - <:str_item< $typedef$; $ofjson$; $tojson$ >> + let javadef = make_javadef _loc l in + <:str_item< $typedef$; $ofjson$; $tojson$; $javadef$>> let o2b = function None -> false | _ -> true ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Generation of Java code from OCaml 2009-09-24 9:45 ` blue storm @ 2009-09-24 11:18 ` Martin Jambon 2009-09-24 12:02 ` blue storm 0 siblings, 1 reply; 12+ messages in thread From: Martin Jambon @ 2009-09-24 11:18 UTC (permalink / raw) To: blue storm; +Cc: Mykola Stryebkov, David Allsopp, caml-list blue storm wrote: > In case it helps, below is a basic patch against json-static (SVN > trunk, 3.10 version). On your example it produces the following code : [...] Yes, patching the original code of json-static would work but it's not ideal. Maybe Deriving is a better choice (http://code.google.com/p/deriving/). I just say "maybe" because I've never used it. Or you can write your own camlp4 extension from scratch and find out how to use one of the predefined filters that would let you output only record-derived data. Note that if you're already using json-static but need to duplicate type definitions, you can do as follows: type foo = { bar : int } type json foo = predefined { bar : int } Martin -- http://mjambon.com/ ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Generation of Java code from OCaml 2009-09-24 11:18 ` Martin Jambon @ 2009-09-24 12:02 ` blue storm 2009-09-24 12:19 ` Martin Jambon 2009-09-26 7:37 ` ygrek 0 siblings, 2 replies; 12+ messages in thread From: blue storm @ 2009-09-24 12:02 UTC (permalink / raw) To: Martin Jambon; +Cc: Mykola Stryebkov, David Allsopp, caml-list On Thu, Sep 24, 2009 at 1:18 PM, Martin Jambon <martin.jambon@ens-lyon.org> wrote: > Yes, patching the original code of json-static would work but it's not ideal. >From the example given, it seems that the original poster already uses json-static. In that case, I think that reusing the code logic is a good idea (coherent behaviour, etc.). I suppose that you dislike the "patching" solution as it is not easily reusable (one cannot use the upstream json-static anymore). What about factorising json-static to allow adding arbitrary code generators (represented as functions from (string * type_def) list to a camlp4 Ast) at camlp4-time ? You would have a design similar to type-conv, wich allows adding new generators without modifying type-conv itself. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Generation of Java code from OCaml 2009-09-24 12:02 ` blue storm @ 2009-09-24 12:19 ` Martin Jambon 2009-10-03 12:16 ` Anil Madhavapeddy 2009-09-26 7:37 ` ygrek 1 sibling, 1 reply; 12+ messages in thread From: Martin Jambon @ 2009-09-24 12:19 UTC (permalink / raw) To: blue storm; +Cc: Mykola Stryebkov, David Allsopp, caml-list blue storm wrote: > On Thu, Sep 24, 2009 at 1:18 PM, Martin Jambon > <martin.jambon@ens-lyon.org> wrote: >> Yes, patching the original code of json-static would work but it's not ideal. > >>From the example given, it seems that the original poster already uses > json-static. In that case, I think that reusing the code logic is a > good idea (coherent behaviour, etc.). I suppose that you dislike the > "patching" solution as it is not easily reusable (one cannot use the > upstream json-static anymore). Of course, the internals of json-static are much more likely to change than its user interface. This may however not be such a big problem here in practice. The problem is more that it's not compatible with other possible extensions of json-static provided by 3rd parties. > What about factorising json-static to allow adding arbitrary code > generators (represented as functions from (string * type_def) list to > a camlp4 Ast) at camlp4-time ? You would have a design similar to > type-conv, wich allows adding new generators without modifying > type-conv itself. Oh yes, there's type-conv too. I don't know the pros and cons of using either type-conv or deriving. If anyone knows, a brief comparison would be helpful. Martin -- http://mjambon.com/ ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Generation of Java code from OCaml 2009-09-24 12:19 ` Martin Jambon @ 2009-10-03 12:16 ` Anil Madhavapeddy 2009-10-03 17:27 ` blue storm 0 siblings, 1 reply; 12+ messages in thread From: Anil Madhavapeddy @ 2009-10-03 12:16 UTC (permalink / raw) To: Martin Jambon; +Cc: blue storm, caml-list [-- Attachment #1: Type: text/plain, Size: 1459 bytes --] On 24 Sep 2009, at 13:19, Martin Jambon wrote: > > Oh yes, there's type-conv too. I don't know the pros and cons of > using either > type-conv or deriving. If anyone knows, a brief comparison would be > helpful. > The nice thing about using type-conv is that syntax extensions can be composed quite easily, as long as the generators themselves don't depend too much on custom type syntax (e.g. when using sexplib, don't use the special sexp_option/sexp_opaque types). I've ported your json-static extension over to type-conv so that we can use a combination of json/sexp and the (still in development) ORM extension side-by-side with a single type declaration, e.g. type t = { foo: string; bar: int } with orm (debug: all), json ... which generates both persistence functions and the json functions from the single type. Right now it's fairly awkward to do this with json-static and the 'predefined' keyword as it requires duplicating types. The ported version of json-static to type-conv is available at: http://github.com/avsm/caml-type-conv-json/ The only thing I haven't quite worked out yet is the quotation to pattern-match type applications to detect things like "(string, unit) Hashtbl.t" the way the current json-static does via the grammar extension. Most other types like char, int32/64, unit, poly variants, etc should all work. There's a simple testcase in check_tc.ml in the same repository. -anil [-- Attachment #2: Type: text/html, Size: 1989 bytes --] ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Generation of Java code from OCaml 2009-10-03 12:16 ` Anil Madhavapeddy @ 2009-10-03 17:27 ` blue storm 2009-10-03 18:29 ` Anil Madhavapeddy 0 siblings, 1 reply; 12+ messages in thread From: blue storm @ 2009-10-03 17:27 UTC (permalink / raw) To: Anil Madhavapeddy; +Cc: Martin Jambon, caml-list On Sat, Oct 3, 2009 at 2:16 PM, Anil Madhavapeddy <anil@recoil.org> wrote: > The only thing I haven't quite worked out yet is the quotation to > pattern-match type applications to detect things like "(string, unit) > Hashtbl.t" the way the current json-static does via the grammar extension. > -anil Below are two patches (from `git log -u`) adding the relevant features. ########################## diff --git a/json-static/pa_json_tc.ml b/json-static/pa_json_tc.ml index f1d21e7..09b7937 100644 --- a/json-static/pa_json_tc.ml +++ b/json-static/pa_json_tc.ml @@ -494,11 +494,15 @@ and process_td _loc = function | <:ctyp< int64 >> -> Int64 | <:ctyp< unit >> -> Unit | <:ctyp< char >> -> Char + | <:ctyp< number >> -> Number | <:ctyp< option $t$ >> -> Option (_loc, process_td _loc t) | <:ctyp< list $t$ >> -> List (_loc, process_td _loc t) | <:ctyp< array $t$ >> -> Array (_loc, process_td _loc t) - + | <:ctyp< assoc $t$ >> as assoc -> + (match t with + | <:ctyp< (string * $t$) >> -> Assoc (_loc, process_td _loc t) + | _ -> failwith "must be of the form (string * ...) assoc") | <:ctyp< < $cs$ > >> -> Object (process_fields _loc cs) | <:ctyp< { $cs$ } >> -> Record (process_fields _loc cs) @@ -512,8 +516,13 @@ and process_td _loc = function (Ast.list_of_ctyp tp []) in Tuple tps - | <:ctyp< $uid:id$.t >> -> Custom id (* XXX broken, how to check for TyApp? *) + | <:ctyp< Hashtbl.t string $x$ >> -> Hashtbl (_loc, process_td _loc x) + | <:ctyp< json_type >> + | <:ctyp< Json_type.json_type >> + | <:ctyp< Json_type.t >> + -> Raw | <:ctyp< $lid:id$ >> -> Name id + | <:ctyp< $uid:id$.t >> -> Custom id | _ -> failwith "unknown type" open Pa_type_conv ########################## diff --git a/json-static/check.ml b/json-static/check.ml index 19bac81..ff0186b 100644 --- a/json-static/check.ml +++ b/json-static/check.ml @@ -33,3 +33,4 @@ and b = int type json c = (string * d * d) list and d = [ `A ] + diff --git a/json-static/check_tc.ml b/json-static/check_tc.ml index b362ad2..3105800 100644 --- a/json-static/check_tc.ml +++ b/json-static/check_tc.ml @@ -31,3 +31,6 @@ let _ = assert (json_o#foo = o#foo); assert (json_o#bar = o#bar); prerr_endline json_string + +type c = (string, unit) Hashtbl.t with json +type d = (string * float) assoc with json diff --git a/json-static/pa_json_tc.ml b/json-static/pa_json_tc.ml index 09b7937..5c76819 100644 --- a/json-static/pa_json_tc.ml +++ b/json-static/pa_json_tc.ml @@ -448,6 +448,9 @@ let expand_typedefs _loc l = let tojson = make_tojson _loc l in <:str_item< $ofjson$; $tojson$ >> +let type_fail ctyp msg = + Loc.raise (Ast.loc_of_ctyp ctyp) (Failure msg) + let rec process_tds tds = let rec fn ty = match ty with @@ -455,7 +458,7 @@ let rec process_tds tds = fn tyl @ (fn tyr) |Ast.TyDcl (_loc, id, _, ty, []) -> [ (_loc, id ) , (_loc, process_td _loc ty) ] - |_ -> failwith "process_tds: unexpected type" + | other -> type_fail other "process_tds: unexpected AST" in fn tds and process_fields _loc cs = @@ -463,7 +466,7 @@ and process_fields _loc cs = | <:ctyp< $t1$; $t2$ >> -> fn t1 @ (fn t2) | <:ctyp< $lid:id$ : mutable $t$ >> -> fnt ~mut:true ~id ~t | <:ctyp< $lid:id$ : $t$ >> -> fnt ~mut:false ~id ~t - | _ -> failwith "unexpected ast" + | other -> type_fail other "process_fields: unexpected AST" and fnt ~mut ~id ~t = [ { field_caml_name = id; field_json_name = id; field_type = (_loc, process_td _loc t); @@ -482,7 +485,7 @@ and process_constructor _loc rf = | <:ctyp< $uid:id$ >> -> { cons_caml_name=id; cons_json_name=id; cons_caml_loc=_loc; cons_json_loc=_loc; cons_args=[] } - | _ -> failwith "process_constructor: unexpected AST" + | other -> type_fail other "process_constructor: unexpected AST" ) (Ast.list_of_ctyp rf []) and process_td _loc = function @@ -502,7 +505,7 @@ and process_td _loc = function | <:ctyp< assoc $t$ >> as assoc -> (match t with | <:ctyp< (string * $t$) >> -> Assoc (_loc, process_td _loc t) - | _ -> failwith "must be of the form (string * ...) assoc") + | other -> type_fail assoc "must be of the form (string * ...) assoc") | <:ctyp< < $cs$ > >> -> Object (process_fields _loc cs) | <:ctyp< { $cs$ } >> -> Record (process_fields _loc cs) @@ -523,7 +526,7 @@ and process_td _loc = function -> Raw | <:ctyp< $lid:id$ >> -> Name id | <:ctyp< $uid:id$.t >> -> Custom id - | _ -> failwith "unknown type" + | other -> type_fail other "unknown type" open Pa_type_conv let _ = ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Generation of Java code from OCaml 2009-10-03 17:27 ` blue storm @ 2009-10-03 18:29 ` Anil Madhavapeddy 0 siblings, 0 replies; 12+ messages in thread From: Anil Madhavapeddy @ 2009-10-03 18:29 UTC (permalink / raw) To: blue storm; +Cc: Martin Jambon, caml-list [-- Attachment #1: Type: text/plain, Size: 1174 bytes --] On 3 Oct 2009, at 18:27, blue storm wrote: > On Sat, Oct 3, 2009 at 2:16 PM, Anil Madhavapeddy <anil@recoil.org> > wrote: >> The only thing I haven't quite worked out yet is the quotation to >> pattern-match type applications to detect things like "(string, unit) >> Hashtbl.t" the way the current json-static does via the grammar >> extension. >> -anil > > Below are two patches (from `git log -u`) adding the relevant > features. > (snip) > - > + | <:ctyp< assoc $t$ >> as assoc -> > + (match t with > + | <:ctyp< (string * $t$) >> -> Assoc (_loc, process_td _loc t) > + | _ -> failwith "must be of the form (string * ...) assoc") > | <:ctyp< < $cs$ > >> -> Object (process_fields _loc cs) > | <:ctyp< { $cs$ } >> -> Record (process_fields _loc cs) Thanks; my goal is to avoid putting in special types into type-conv generators though ('assoc' here), so they can be used alongside other generators too. It seems reasonable to just special-case "Hashtbl.t string $t$" and "list ( string * $t$ )", since JSON objects must have a string as the key. I've pushed a patch which does that to my tree, along with some of your other changes. -anil [-- Attachment #2: Type: text/html, Size: 1959 bytes --] ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Generation of Java code from OCaml 2009-09-24 12:02 ` blue storm 2009-09-24 12:19 ` Martin Jambon @ 2009-09-26 7:37 ` ygrek 1 sibling, 0 replies; 12+ messages in thread From: ygrek @ 2009-09-26 7:37 UTC (permalink / raw) To: caml-list [-- Attachment #1: Type: text/plain, Size: 567 bytes --] On Thu, 24 Sep 2009 14:02:14 +0200 blue storm <bluestorm.dylc@gmail.com> wrote: > What about factorising json-static to allow adding arbitrary code > generators (represented as functions from (string * type_def) list to > a camlp4 Ast) at camlp4-time ? You would have a design similar to > type-conv, wich allows adding new generators without modifying > type-conv itself. That would be really useful for other kinds of serialization. I would be glad to add json-static-like interface for bencode and php_serialize. -- ygrek http://ygrek.org.ua [-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --] ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2009-10-03 18:29 UTC | newest] Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2009-09-23 18:15 Generation of Java code from OCaml Mykola Stryebkov 2009-09-23 19:57 ` [Caml-list] " Richard Jones 2009-09-23 22:54 ` Mykola Stryebkov 2009-09-24 8:03 ` David Allsopp 2009-09-24 9:45 ` blue storm 2009-09-24 11:18 ` Martin Jambon 2009-09-24 12:02 ` blue storm 2009-09-24 12:19 ` Martin Jambon 2009-10-03 12:16 ` Anil Madhavapeddy 2009-10-03 17:27 ` blue storm 2009-10-03 18:29 ` Anil Madhavapeddy 2009-09-26 7:37 ` ygrek
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox