From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Delivered-To: caml-list@yquem.inria.fr Received: from nez-perce.inria.fr (nez-perce.inria.fr [192.93.2.78]) by yquem.inria.fr (Postfix) with ESMTP id E5506BC75 for ; Fri, 25 Feb 2005 01:30:50 +0100 (CET) Received: from pauillac.inria.fr (pauillac.inria.fr [128.93.11.35]) by nez-perce.inria.fr (8.13.0/8.13.0) with ESMTP id j1P0UoUQ002833 for ; Fri, 25 Feb 2005 01:30:50 +0100 Received: from nez-perce.inria.fr (nez-perce.inria.fr [192.93.2.78]) by pauillac.inria.fr (8.7.6/8.7.3) with ESMTP id BAA29225 for ; Fri, 25 Feb 2005 01:30:49 +0100 (MET) Received: from kurims.kurims.kyoto-u.ac.jp (kurims.kurims.kyoto-u.ac.jp [130.54.16.1]) by nez-perce.inria.fr (8.13.0/8.13.0) with ESMTP id j1P0UmVA002830 for ; Fri, 25 Feb 2005 01:30:49 +0100 Received: from localhost (suiren [130.54.16.25]) by kurims.kurims.kyoto-u.ac.jp (8.13.1/8.13.1) with ESMTP id j1P0Ujut022249; Fri, 25 Feb 2005 09:30:45 +0900 (JST) Date: Fri, 25 Feb 2005 09:30:41 +0900 (JST) Message-Id: <20050225.093041.55484334.garrigue@math.nagoya-u.ac.jp> To: cstork@ics.uci.edu Cc: caml-list@inria.fr Subject: Re: [Caml-list] Unquantifiable escaping type in variation of visitor pattern From: Jacques Garrigue In-Reply-To: <20050224121635.GA22511@anthony.ics.uci.edu> References: <20050222172907.GA8376@anthony.ics.uci.edu> <20050223.120815.41202930.garrigue@math.nagoya-u.ac.jp> <20050224121635.GA22511@anthony.ics.uci.edu> X-Mailer: Mew version 4.1.53 on Emacs 21.3 / Mule 5.0 (SAKAKI) Mime-Version: 1.0 Content-Type: Multipart/Mixed; boundary="--Next_Part(Fri_Feb_25_09_30_41_2005_158)--" Content-Transfer-Encoding: 7bit X-Miltered: at nez-perce with ID 421E71BA.000 by Joe's j-chkmail (http://j-chkmail.ensmp.fr)! X-Miltered: at nez-perce with ID 421E71B8.001 by Joe's j-chkmail (http://j-chkmail.ensmp.fr)! X-Spam: no; 0.00; caml-list:01 escaping:01 subtyping:01 subtyping:01 subtype:01 nodes:01 variants:01 recursion:01 nodes:01 motion-twin:01 parametrized:01 desc:01 desc:01 mutable:01 val:01 X-Attachments: name="reply.ml" X-Spam-Checker-Version: SpamAssassin 3.0.2 (2004-11-16) on yquem.inria.fr X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=disabled version=3.0.2 X-Spam-Level: ----Next_Part(Fri_Feb_25_09_30_41_2005_158)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit From: Christian Stork > > But in your particular example there is no subtyping at all, so there > > should be no problem anyway. > > I don't know which particular subtyping you refer to, but, of course, I > intend to subtype the rules and visitors. I should have looked at your code. Indeed you're using subtyping, but not on nodes, so it's ok. Yet I still don't understand what your code is about. I see nothing specific in your classes, justifying using object-orientation rather than normal variants. Also, the way you're coercing to an abstract rule, you're forgetting all useful information, to keep only the rule name. I don't see how you can make any useful use of that. Anyway, one can get rid at least part of the recursion, by restructuring your types in a more standard way: putting the common parts outside rather than inside. And why do you need your nodes to refer to their parent? When you walk the tree, it is clear who the parent is. Here is a slightly modified (more readable) version of your code, but I still don't see the point. What about having a look at a more functional view on DTD's, like in xmllight. http://tech.motion-twin.com/xmllight Jacques Garrigue ----Next_Part(Fri_Feb_25_09_30_41_2005_158)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="reply.ml" (** The parametrized version of the node type *) type 'a node_desc = | NTerm of 'tr | NInt of 'ir * int64 option ref | NStr of 'sr * string option ref | NAggr of 'ar * 'a node' list ref | NChoice of 'cr * 'a node' option ref | NList of 'lr * 'a node' list ref constraint 'a = (** Common attributes of nodes are collected in this record *) and 'a node' = { desc : 'a node_desc; mutable parent : 'a node' option; } constraint 'a = (** All the different kinds of rules follow. *) (** This abstract base class gathers common functionality of rules *) class virtual abstractRule (name:string) = object (self) method name = name end and virtual rules = object (self : ) end (** Terminal rules *) and termRule name = object (self) inherit abstractRule name method kind = "terminalRule" method to_string = name ^ "." method makeTermNode (parent : rules node' option) = {desc = NTerm(self :> termRule); parent = parent} end (** Integer rules *) and intRule name = object (self) inherit abstractRule name method kind = "integerRule" method to_string = name ^ " =^= INTEGER." method makeIntNode (parent : rules node' option) int_opt = {desc = NInt ((self :> intRule), ref int_opt); parent = parent} end (** String rules *) and strRule name = object (self) inherit abstractRule name method kind = "stringRule" method to_string = name ^ " =^= STRING." method makeStrNode (parent : rules node' option) str_opt = {desc = NStr ((self :> strRule), ref str_opt); parent = parent} end (** Aggregate rules *) and aggrRule name = object (self) inherit abstractRule name method kind = "aggregateRule" val mutable parts = ([] : abstractRule list) method parts = parts method initParts parts' = parts <- parts' method to_string = name ^ " =^= " ^ (String.concat "; " (List.map (fun p -> p#name) parts)) ^ "." method makeAggrNode (parent : rules node' option) kid_list = {desc = NAggr ((self :> aggrRule), ref kid_list); parent = parent} end (** Choice rules *) and choiceRule name = object (self) inherit abstractRule name method kind = "choiceRule" val mutable alts = ([] : abstractRule list) method alts = alts method initAlts alts' = alts <- alts' method to_string = name ^ " =^= " ^ (String.concat " | " (List.map (fun a -> a#name) alts)) ^ "." method makeChoiceNode (parent : rules node' option) kid_opt = {desc = NChoice ((self :> choiceRule), ref kid_opt); parent = parent} end (** List rules *) and listRule name = object (self) inherit abstractRule name method kind = "listRule" val mutable item = (None : abstractRule option) method item : abstractRule option = item method initItem item' = item <- Some item' method to_string = name ^ " =^= (" ^ (match item with None -> "" | Some i -> i#name) ^ ")*." method makeListNode (parent : rules node' option) kid_list = {desc = NList ((self :> listRule), ref kid_list); parent = parent} end (* Finally shorter types *) type node = rules node' (*** Re mutable rule fields ***) (* This is how I end up generating grammars at runtime. *) (* Simple Test Grammar for plus/times expressions *) let exp = new choiceRule "exp" let intLit = new intRule "intLit" let binExp = new aggrRule "binExp" let binOp = new choiceRule "binOp" let plusOp = new termRule "plusOp" let timesOp = new termRule "timesOp" let startrule = exp;; exp#initAlts [ (intLit :> abstractRule); (binExp :> abstractRule); ];; binExp#initParts[ (exp :> abstractRule); (binOp :> abstractRule); (exp :> abstractRule) ];; binOp#initAlts [ (plusOp :> abstractRule); (timesOp :> abstractRule); ];; (*** Re parent ref cell in nCommon ***) (* Simple Test Tree for the expression with the int litereral "0" *) (* This is how I intended to write it but it does not compile due to "This kind of expression is not allowed as right-hand side of `let rec'" which is interesting since it does not contain a new statement. *) (* let rec t = exp#makeChoiceNode None (Some (intLit#makeIntNode (Some t) (Some (Int64.of_int 3))));; *) (* The tree can be generated and later fixed like this, but this requires parent refs: *) let t = exp#makeChoiceNode None (Some (intLit#makeIntNode None (Some (Int64.of_int 3))));; (* helpers for fixParents below *) let kids node = match node.desc with | NTerm _ | NInt _ | NStr _ | NChoice (_,{contents=None}) -> [] | NChoice (_,{contents=Some k}) -> [k] | NAggr (_,{contents=ks}) | NList (_,{contents=ks}) -> ks let rec fixParents (p:node option) (n:node) = n.parent <- p; List.iter (fun k -> fixParents (Some n) k) (kids n);; fixParents None t;; (* I guess this is how it should be done. No need to put parent in a ref if trees can always be defined like this: *) let rec (t:node) = {desc = NChoice (exp, ref(Some{desc = NInt (intLit, ref(Some(Int64.of_int 0))); parent = Some t})); parent = None};; ----Next_Part(Fri_Feb_25_09_30_41_2005_158)----