From mboxrd@z Thu Jan 1 00:00:00 1970 Received: (from majordomo@localhost) by pauillac.inria.fr (8.7.6/8.7.3) id AAA28094; Fri, 27 Jun 2003 00:52:12 +0200 (MET DST) X-Authentication-Warning: pauillac.inria.fr: majordomo set sender to owner-caml-list@pauillac.inria.fr using -f Received: from concorde.inria.fr (concorde.inria.fr [192.93.2.39]) by pauillac.inria.fr (8.7.6/8.7.3) with ESMTP id AAA28350 for ; Fri, 27 Jun 2003 00:52:11 +0200 (MET DST) Received: from sockmel.bononia.it (sockmel.bononia.it [193.201.40.5]) by concorde.inria.fr (8.11.1/8.11.1) with ESMTP id h5QMqAj14976 for ; Fri, 27 Jun 2003 00:52:10 +0200 (MET DST) Received: from fistandantilus.takhisis.org (sockmel.bononia.it [193.201.40.5]) by sockmel.bononia.it (Postfix) with ESMTP id 48EB056F0B for ; Fri, 27 Jun 2003 00:52:07 +0200 (CEST) Received: by fistandantilus.takhisis.org (Postfix, from userid 3148) id AF78227408B; Fri, 27 Jun 2003 00:52:01 +0200 (CEST) Date: Fri, 27 Jun 2003 00:52:01 +0200 From: Stefano Zacchiroli To: caml-list@inria.fr Subject: [Caml-list] camlp4 syntax extension for hashtbl Message-ID: <20030626225201.GD14529@fistandantilus.takhisis.org> Mail-Followup-To: caml-list@inria.fr Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="yrj/dFKFPuw6o+aM" Content-Disposition: inline User-Agent: Mutt/1.5.4i X-Spam: no; 0.00; bononia:01 camlp:01 hashtbl:01 foo:01 expr:01 fallback:01 quux:01 -pp:01 pcaml:01 lident:01 patt:01 cmo:01 bigarray:01 bindings:01 ocaml:01 X-Attachments: name="hashtbl_ext.ml" Sender: owner-caml-list@pauillac.inria.fr Precedence: bulk --yrj/dFKFPuw6o+aM Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Just to practice a bit with camlp4 I've written a simple syntax extension for hashtbl usage. I will attach the .ml hoping that it will be useful and hoping in some feedback from camlp4 gurus :-) Intended usage (more infos at the beginning of the source file): let tbl = {} (* empty tbl *) let tbl = {}|12| (* as above, size 12 *) let tbl = {["foo", 1; "bar", 2]} (* filled tbl, size 2 *) let tbl = {["foo", 1; "bar", 2]}|17| (* filled tbl, size 17 *) tbl{"foo"} (* Hashtbl.find *) tbl{["foo"]} (* Hashtbl.find_all *) tbl{?"foo"} (* Hashtbl.mem *) tbl{"foo"} <- 1 (* Hashtbl.replace *) tbl{"foo"} <= 1 (* Hashtbl.add *) tbl{"foo"} -> (* Hashtbl.remove *) keys tbl (* Perl "keys" operator *) values tbl (* Perl "values" operator *) If anybody wants to have a look at it, I need some advice/feedback on the following issues: - how to cope with errors (now they are _really_ strange :-) - I've used everywhere expressions of LEVEL "simple" to avoid conflicts with bigarray pattern syntax, any other solution? - my extension of standard "expr1" level now begins with a fallback on "simple" expression. What I want to do is to put those rules after the rules for "simple" expressions, but I had not found a better way to do it ... - what about the chosen syntax? suggestions? - I had not found a way to define an integer constant and use it inside a quotation, the only solution I had found is to pass from strings: let foo = "10" in <:expr< $int:foo$ >> what am I missing? TIA for the feedback, Cheers. -- Stefano Zacchiroli -- Master in Computer Science @ Uni. Bologna, Italy zack@{cs.unibo.it,debian.org,bononia.it} - http://www.bononia.it/zack/ " I know you believe you understood what you think I said, but I am not sure you realize that what you heard is not what I meant! " -- G.Romney --yrj/dFKFPuw6o+aM Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="hashtbl_ext.ml" (* Hashtbl creation (* create an hashtbl of with (initial size = magic_size) *) let tbl = {} (* create an hashtbl of initial size 12 *) let tbl = {}|12| (* create an hashbbl of size 3, with bindings specified in an associative-list-like manner. If a key occurs more than once the first one appearing in the list will be the more recent one. Every expression returning an associative list could be used inside braces *) let tbl = {["foo", 1; "bar", 2; "quux", 3]} (* as above, with initial size 17 *) let tbl = {["foo", 1; "bar", 2; "quux", 3]}|17| Hashtbl lookup tbl{"foo"} (* Hashtbl.find tbl "foo" *) tbl{["foo"]} (* Hashtbl.find_all tbl "foo" *) tbl{?"foo"} (* Hashtbl.mem tbl "foo" *) Hashtbl insertion tbl{"foo"} <- 1 (* Hashtbl.replace tbl "foo" 1 *) tbl{"foo"} <= 1 (* Hashtbl.add tbl "foo" 1 *) Hashtbl deletion tbl{"foo"} -> (* Hashtbl.remove tbl "foo" *) Perl-like operators keys tbl (* list all keys in tbl *) values tbl (* list all values in tbl, multiple binding are reported more than once *) Usage (assuming that the .cmo is in a directory that is in the camlp4 path, otherwise you need to add -I to camlp4{o,r} as needed): ocaml{c,opt} -pp "camlp4{o,r} hashtbl_ext.cmo" *) open Pcaml let magic_size = 1024 let hashtbl_find loc tbl k = <:expr< Hashtbl.find $tbl$ $k$ >> let hashtbl_find_all loc tbl k = <:expr< Hashtbl.find_all $tbl$ $k$ >> let hashtbl_mem loc tbl k = <:expr< Hashtbl.mem $tbl$ $k$ >> let hashtbl_add loc tbl k v = <:expr< Hashtbl.add $tbl$ $k$ $v$ >> let hashtbl_replace loc tbl k v = <:expr< Hashtbl.replace $tbl$ $k$ $v$ >> let hashtbl_remove loc tbl k = <:expr< Hashtbl.remove $tbl$ $k$ >> let hashtbl_keys loc tbl = <:expr< Hashtbl.fold (fun k _ acc -> [k :: acc]) $tbl$ [] >> let hashtbl_values loc tbl = <:expr< Hashtbl.fold (fun _ v acc -> [v :: acc]) $tbl$ [] >> let magic_size = string_of_int magic_size let hashtbl_create loc size content = <:expr< let size = match $int:size$ with [ 0 -> match $content$ with [ [] -> $int:magic_size$ | _ -> List.length $content$ ] | v -> v ] in let table = Hashtbl.create size in do { List.iter (fun (k,v) -> Hashtbl.add table k v) $content$; table } >> EXTEND expr: LEVEL "expr1" [ [ e = expr LEVEL "simple" -> e | table = expr LEVEL "simple"; "{"; key = expr LEVEL "simple"; "}" -> hashtbl_find loc table key | table = expr LEVEL "simple"; "{"; "["; key = expr LEVEL "simple"; "]"; "}" -> hashtbl_find_all loc table key | table = expr LEVEL "simple"; "{"; "?"; key = expr LEVEL "simple"; "}" -> hashtbl_mem loc table key | table = expr LEVEL "simple"; "{"; key = expr LEVEL "simple"; "}"; "<-"; value = expr LEVEL "simple" -> hashtbl_replace loc table key value | table = expr LEVEL "simple"; "{"; key = expr LEVEL "simple"; "}"; "<="; value = expr LEVEL "simple" -> hashtbl_add loc table key value | table = expr LEVEL "simple"; "{"; key = expr LEVEL "simple"; "}"; "->" -> hashtbl_remove loc table key ] ]; expr: LEVEL "simple" [ [ "keys"; e = SELF -> hashtbl_keys loc e | "values"; e = SELF -> hashtbl_values loc e ] ]; let_binding: FIRST [ [ id = [ id = LIDENT -> id | "_" -> "" ]; "="; "{"; content = OPT [ e = expr LEVEL "simple" -> e ]; "}"; size = OPT [ "|"; size = INT; "|" -> size ] -> let size = match size with None -> "0" | Some v -> v in let content = match content with None -> <:expr< [] >> | Some c -> c in ((match id with "" -> <:patt< _ >> | id -> <:patt< $lid:id$ >>), hashtbl_create loc size content) ] ]; END --yrj/dFKFPuw6o+aM-- ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners