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 mail1-relais-roc.national.inria.fr (mail1-relais-roc.national.inria.fr [192.134.164.82]) by yquem.inria.fr (Postfix) with ESMTP id 7408BBC57 for ; Wed, 9 Jun 2010 09:51:38 +0200 (CEST) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: ArUMAMPkDkzNm0EP/2dsb2JhbACSMIkIgwxxvQyFGASDSQ X-IronPort-AV: E=Sophos;i="4.53,390,1272837600"; d="scan'208";a="60928335" Received: from virginia.nps.edu ([205.155.65.15]) by mail1-smtp-roc.national.inria.fr with ESMTP; 09 Jun 2010 09:51:37 +0200 Received: from Adric.ern.nps.edu ([172.20.216.170]) by virginia.nps.edu with Microsoft SMTPSVC(6.0.3790.4675); Wed, 9 Jun 2010 00:51:35 -0700 Received: by Adric.ern.nps.edu (Postfix, from userid 760) id E3754173BB; Wed, 9 Jun 2010 00:47:03 -0700 (PDT) From: oleg@okmij.org To: martin.potier@gmail.com Cc: caml-list@inria.fr Subject: Re: Caml typed AST Message-Id: <20100609074703.E3754173BB@Adric.ern.nps.edu> Date: Wed, 9 Jun 2010 00:47:03 -0700 (PDT) X-OriginalArrivalTime: 09 Jun 2010 07:51:35.0696 (UTC) FILETIME=[95A8D100:01CB07A8] X-Spam: no; 0.00; oleg:01 typedtree:01 ocaml:01 parses:01 val:01 typedtree:01 desc:01 texp:01 asttypes:01 nonrecursive:01 desc:01 tpat:01 abstr:01 lexing:01 lexing:01 Martin Potier wrote: > I'd like to know if there is a way to retrieve a typped AST from Caml. The function read_type_exp : string -> Typedtree.expression takes a string of OCaml code, parses it, typechecks and returns the typed tree. For example, evaluating let test1 = read_type_exp "let x = 21 and twice y = 2 * y in twice x";; prints val test1 : Typedtree.expression = {Typedtree.exp_desc = Typedtree.Texp_let (Asttypes.Nonrecursive, [({Typedtree.pat_desc = Typedtree.Tpat_var ; Typedtree.pat_loc = {Location.loc_start = {Lexing.pos_fname = ""; Lexing.pos_lnum = 1; Lexing.pos_bol = 0; Lexing.pos_cnum = 4}; Location.loc_end = {Lexing.pos_fname = ""; Lexing.pos_lnum = 1; Lexing.pos_bol = 0; Lexing.pos_cnum = 5}; Location.loc_ghost = false}; Typedtree.pat_type = {Types.desc = Types.Tlink {Types.desc = Types.Tconstr (Path.Pident , [], {contents = Types.Mnil}); Types.level = 100000000; Types.id = 649}; Types.level = 59; Types.id = 647}; Typedtree.pat_env = }, {Typedtree.exp_desc = Typedtree.Texp_constant (Asttypes.Const_int 21); Typedtree.exp_loc = {Location.loc_start = {Lexing.pos_fname = ""; Lexing.pos_lnum = 1; Lexing.pos_bol = 0; Lexing.pos_cnum = 8}; Location.loc_end = {Lexing.pos_fname = ""; Lexing.pos_lnum = 1; Lexing.pos_bol = 0; Lexing.pos_cnum = 10}; Location.loc_ghost = false}; Typedtree.exp_type = {Types.desc = Types.Tconstr (Path.Pident , [], {contents = Types.Mnil}); Types.level = 100000000; Types.id = 649}; Typedtree.exp_env = }); ...plus many more lines.... (and this is only the part that corresponds let x = 21). As you can see (although probably not easily) the type-checker has figured out that both x and 21 have the type int. The module typing/printtyp.mli in the OCaml distribution has a few nicer printing functions. Here is the code (top-level script) (* In the directory directives below, replace /usr/ports/lang/ocaml/work/ocaml-3.11.1/ with the complete path to your ocaml distribution. It is assumed the directory contains the made OCaml. *) #directory "/usr/ports/lang/ocaml/work/ocaml-3.11.1/parsing";; #directory "/usr/ports/lang/ocaml/work/ocaml-3.11.1/typing";; #directory "/usr/ports/lang/ocaml/work/ocaml-3.11.1/toplevel";; #directory "/usr/ports/lang/ocaml/work/ocaml-3.11.1/utils";; (* Please do NOT change the order of the following directives! *) (* This must be loaded first! It is stateful, and affects Predef *) #load "ident.cmo";; (* Load the rest of the compiler *) #load "misc.cmo";; #load "path.cmo";; #load "types.cmo";; #load "btype.cmo";; #load "tbl.cmo";; #load "subst.cmo";; #load "predef.cmo";; #load "datarepr.cmo";; #load "config.cmo";; #load "consistbl.cmo";; #load "clflags.cmo";; #load "env.cmo";; #load "ctype.cmo";; #load "printast.cmo";; #load "oprint.cmo";; #load "primitive.cmo";; #load "printtyp.cmo";; #load "linenum.cmo";; #load "warnings.cmo";; #load "location.cmo";; #load "typetexp.cmo";; #load "includecore.cmo";; #load "typedecl.cmo";; #load "typedtree.cmo";; #load "stypes.cmo";; #load "parmatch.cmo";; #load "typecore.cmo";; #load "includeclass.cmo";; #load "typeclass.cmo";; #load "mtype.cmo";; #load "includemod.cmo";; #load "longident.cmo";; #load "typemod.cmo";; #load "ccomp.cmo";; #load "lexer.cmo";; #load "syntaxerr.cmo";; #load "parser.cmo";; #load "parse.cmo";; (* from driver/compile.ml *) let initial_env () = Config.load_path := [""; "/usr/local/lib/ocaml"]; Env.reset_cache (); Ident.reinit(); try Env.open_pers_signature "Pervasives" Env.initial with Not_found -> failwith "cannot open pervasives.cmi" ;; let env = initial_env() ;; (* toplevel/toploop.ml *) let read_type_exp src_string = let lb = Lexing.from_string src_string in match Parse.implementation lb with | [{Parsetree.pstr_desc = Parsetree.Pstr_eval exp}] -> Ctype.init_def(Ident.current_time()); Typecore.reset_delayed_checks (); let texp = Typecore.type_expression env exp in Typecore.force_delayed_checks (); texp | _ -> failwith "Only expressions are expected" ;; let test1 = read_type_exp "let x = 21 and twice y = 2 * y in twice x";;