From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by yquem.inria.fr (Postfix) with ESMTP id F3C37BC57 for ; Tue, 25 May 2010 09:08:03 +0200 (CEST) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AvcBALgT+0tCbwQZdWdsb2JhbACdehUBFyAGHr0yBYUT X-IronPort-AV: E=Sophos;i="4.53,297,1272837600"; d="scan'208";a="51150874" Received: from out1.smtp.messagingengine.com ([66.111.4.25]) by mail3-smtp-sop.national.inria.fr with ESMTP/TLS/ADH-AES256-SHA; 25 May 2010 09:08:03 +0200 Received: from compute2.internal (compute2.internal [10.202.2.42]) by gateway1.messagingengine.com (Postfix) with ESMTP id 69B58F7D56 for ; Tue, 25 May 2010 03:08:01 -0400 (EDT) Received: from heartbeat2.messagingengine.com ([10.202.2.161]) by compute2.internal (MEProxy); Tue, 25 May 2010 03:08:01 -0400 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=messagingengine.com; h=date:from:to:subject:in-reply-to:message-id:references:mime-version:content-type; s=smtpout; bh=WZBWrNheiYNWG0TA89tkBNMsZq4=; b=oXEcsXGaM3CyKjkAscU5kQ6lIZrM1bKsnENprOUTwK1fPGyhmlpXW2cLtKdJaIGjTTXXFt0OTbuH4L4QtjKFTUcGRbOM2anA9keFG5+9qC/jdDe/LqT57/XruJJfb1THp6XJjH1sZylO3LMS+PGiYnnddsDKLxGHxUIfJXBVHXQ= X-Sasl-enc: NojjhcVv3pIdCLr+KXo9nz6lq+fzGTUZ+uALzTmjRQH9 1274771280 Received: from [192.168.0.3] (unknown [207.251.51.55]) by mail.messagingengine.com (Postfix) with ESMTPSA id BF81E594DB for ; Tue, 25 May 2010 03:08:00 -0400 (EDT) Date: Tue, 25 May 2010 08:44:33 +0200 (CEST) From: Joseph Young X-X-Sender: josyoun@myhome To: caml-list@inria.fr Subject: Re: [Caml-list] Two Different Exception Behaviors in camlp4 on the toplevel In-Reply-To: Message-ID: References: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed X-Spam: no; 0.00; ocaml:01 camlp:01 toplevel:01 camlp:01 syntax:01 bool:01 bool:01 ocaml:01 typechecker:01 sig:01 val:01 val:01 struct:01 typechecker:01 lexer:01 The type checking using phantom types worked great. Thanks. In case it helps anyone else, I'm attaching complete working code below. Joe ---------------------------- $ cat calc.ml open Camlp4.PreCast;; module CamlSyntax= Camlp4OCamlParser.Make( Camlp4OCamlRevisedParser.Make( Camlp4.PreCast.Syntax));; (* The AST for the small calculator *) type loc=CamlSyntax.Loc.t type nonterminal=[`Add | `Sub | `Or | `And | `MixedFn];; type terminal=[`Int of int | `Bool of bool | `Ocaml of (loc*string)];; type calc= | Nonterm of loc*nonterminal*(calc list) | Term of loc*terminal;; module TypeChecker : sig type 'a t val add : loc->int t->int t->int t val sub : loc->int t->int t->int t val or_: loc->bool t->bool t->bool t val and_: loc->bool t->bool t->bool t val mixed: loc->bool t->int t->int t val int_: loc->int -> int t val bool_: loc->bool -> bool t val expose : 'a t->calc end = struct type 'a t=calc let add loc e1 e2 = Nonterm (loc,`Add,[e1;e2]) let sub loc e1 e2 = Nonterm (loc,`Sub,[e1;e2]) let or_ loc e1 e2 = Nonterm (loc,`Or,[e1;e2]) let and_ loc e1 e2 = Nonterm (loc,`And,[e1;e2]) let mixed loc e1 e2 = Nonterm (loc,`MixedFn,[e1;e2]) let int_ loc i = Term (loc,`Int i) let bool_ loc b = Term (loc,`Bool b) let expose e=e end;; open TypeChecker;; (* Grammar for a simple calculator *) module CalcGram = Camlp4.PreCast.MakeGram(Camlp4.PreCast.Lexer);; let (term:calc CalcGram.Entry.t)= CalcGram.Entry.mk "term";; let term_eoi = CalcGram.Entry.mk "Simple calculator quotation";; EXTEND CalcGram GLOBAL: term term_eoi; term: [ "alg" [ e1 = SELF; "+"; e2 = SELF -> Nonterm(_loc,`Add,[e1;e2]) | e1 = SELF; "-"; e2 = SELF -> Nonterm(_loc,`Sub,[e1;e2])] | "bool" [ e1 = SELF; "or"; e2 = SELF -> Nonterm(_loc,`Or,[e1;e2]) | e1 = SELF; "and"; e2 = SELF -> Nonterm(_loc,`And,[e1;e2])] | "other" [ e1 = SELF; "mix"; e2= SELF -> Nonterm(_loc,`MixedFn,[e1;e2])] | "simple" [ "$"; `STRING (e,_); "$" -> Term(_loc,`Ocaml (_loc,e)) | `INT (i, _) -> Term(_loc,`Int i) | "true" -> Term(_loc,`Bool true) | "false" -> Term(_loc,`Bool false) | "("; e = term; ")" -> e ] ]; term_eoi: [[ t = term; `EOI -> t ]]; END;; (* Generates an expression with the location information *) let expr_of_loc _loc= let (a, b, c, d, e, f, g, h) = CamlSyntax.Loc.to_tuple _loc in <:expr< Loc.of_tuple ($`str:a$, $`int:b$, $`int:c$, $`int:d$, $`int:e$, $`int:f$, $`int:g$, $`bool:h$) >> ;; (* Generates an expression with the nonterminal information *) let expr_of_nonterm _loc name= match name with | `Add -> <:expr< add >> | `Sub -> <:expr< sub >> | `Or -> <:expr< or_ >> | `And -> <:expr< and_ >> | `MixedFn -> <:expr< mixed >> ;; (* Generates an expression with the terminal information *) let expr_of_term _loc e= let expr_loc=expr_of_loc _loc in match e with | `Int i -> <:expr< int_ $expr_loc$ $`int:i$ >> | `Bool b -> <:expr< bool_ $expr_loc$ $`bool:b$ >> | `Ocaml(l,e) -> CamlSyntax.Gram.parse_string CamlSyntax.expr_eoi l e ;; (* Converts a calculator AST into an OCaml AST *) let to_expr base_loc prog= let e=CalcGram.parse_string term_eoi base_loc prog in let rec to_expr e= match e with | Nonterm (_loc,name,[e1;e2]) -> let constr= expr_of_nonterm _loc name in let e1=to_expr e1 in let e2=to_expr e2 in <:expr< $constr$ $expr_of_loc _loc$ $e1$ $e2$>> | Term (_loc,data) -> let data= expr_of_term _loc data in <:expr< $data$ >> | _ -> failwith ("Wrong number of arguments.") in to_expr e ;; let expand_calc_quot loc lopt e= to_expr loc e;; Syntax.Quotation.add "calc" Syntax.Quotation.DynAst.expr_tag expand_calc_quot;; ---------------------------- $ cat Makefile all: ocamlc -c -I +camlp4 -I +camlp4/Camlp4Parsers -pp camlp4of -o calc.cmo calc.ml ----------------------------