(* Copyright (C) 2000, HELM Team. * * This file is part of HELM, an Hypertextual, Electronic * Library of Mathematics, developed at the Computer Science * Department, University of Bologna, Italy. * * HELM is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * HELM is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HELM; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * For details, see the HELM World-Wide-Web page, * http://cs.unibo.it/helm/. *) (**************************************************************************) (* *) (* PROJECT HELM *) (* *) (* Andrea Asperti *) (* 28/6/2003 *) (* *) (**************************************************************************) module P = Mpresentation;; module A = CicAst;; let symbol_table = Hashtbl.create 503;; let symbol_table_charcount = Hashtbl.create 503;; let maxsize = 25;; let rec countvar current_size = function (Cic.Anonymous, None) -> current_size + 1 (* underscore *) | (Cic.Anonymous, Some ty) -> countterm current_size ty | (Cic.Name s, None) -> current_size + String.length s | (Cic.Name s, Some ty) -> current_size + countterm current_size ty and countterm current_size t = if current_size > maxsize then current_size else match t with A.AttributedTerm (_,t) -> countterm current_size t | A.Appl l -> List.fold_left countterm current_size l | A.Binder (_,var,body) -> let varsize = countvar current_size var in countterm (varsize + 1) body (* binder *) | A.Case (arg, _, ty, pl) -> let size1 = countterm (current_size+10) arg in (* match with *) let size2 = match ty with None -> size1 | Some ty -> countterm size1 ty in List.fold_left (fun c ((constr,vars),action) -> let size3 = List.fold_left countvar (c+String.length constr) vars in countterm size3 action) size2 pl | A.LetIn (var,s,t) -> let size1 = countvar current_size var in let size2 = countterm size1 s in countterm size2 t | A.LetRec (_,l,t) -> let size1 = List.fold_left (fun c (var,s,_) -> let size1 = countvar c var in countterm size1 s) current_size l in countterm size1 t | A.Ident(s,l) -> List.fold_left (fun c (v,t) -> countterm (c + (String.length v)) t) (current_size + (String.length s)) l | A.Implicit -> current_size + 1 (* underscore *) | A.Meta (_,l) -> List.fold_left (fun c t -> match t with None -> c + 1 (* underscore *) | Some t -> countterm c t) (current_size + 1) l (* num *) | A.Num (s, _) -> current_size + String.length s | A.Sort _ -> current_size + 4 (* sort name *) | A.Symbol (s,_) -> current_size + String.length s ;; let is_big t = ((countterm 0 t) > maxsize) ;; let map_attribute = function `Loc (n,m) -> (Some "helm","loc",(string_of_int n)^" "^(string_of_int m)) | `IdRef s -> (Some "helm","xref",s) ;; let map_attributes = List.map map_attribute ;; let resolve_binder = function `Lambda -> Box.Text([],"\\lambda") | `Pi -> Box.Text([],"\\Pi") | `Exists -> Box.Text([],"\\exists") | `Forall -> Box.Text([],"\\forall") let rec ast2box ?(priority = 0) ?(assoc = false) ?(attr = []) t = if is_big t then bigast2box ~priority ~assoc ~attr t else Box.Object (map_attributes attr, t) and bigast2box ?(priority = 0) ?(assoc = false) ?(attr = []) = function A.AttributedTerm (attr1, t) -> (* attr should be empty, since AtrtributedTerm are not supposed to be directly nested *) bigast2box ~priority ~assoc ~attr:(attr1::~attr) t | A.Appl l -> Box.H (map_attributes attr, [Box.Text([],"("); Box.V([],List.map ast2box l); Box.Text([],")")]) | A.Binder(kind, var, body) -> Box.V(map_attributes attr, [Box.H([],[resolve_binder kind; Box.smallskip; make_var var; Box.Text([],".")]); Box.indent (ast2box body)]) | A.Case(arg, _, ty, pl) -> let make_rule sep ((constr,vars),rhs) = if (is_big rhs) then Box.V([],[Box.H([],[Box.Text([],sep); Box.smallskip; make_pattern constr vars; Box.smallskip; Box.Text([],"->")]); Box.indent (bigast2box rhs)]) else Box.H([],[Box.Text([],sep); Box.smallskip; make_pattern constr vars; Box.smallskip; Box.Text([],"->"); Box.smallskip; Box.Object([],rhs)]) in let plbox = match pl with [] -> Box.Text([],"[]") | r::tl -> Box.H([], [Box.V([], (make_rule "[" r)::(List.map (make_rule "|") tl)); Box.Text([],"]")]) in if is_big arg then Box.V(map_attributes attr, [Box.Text([],"match"); Box.H([],[Box.skip; bigast2box arg; Box.smallskip; Box.Text([],"with")]); plbox]) else Box.V(map_attributes attr, [Box.H(map_attributes attr, [Box.Text([],"match"); Box.smallskip; ast2box arg; Box.smallskip; Box.Text([],"with")]); plbox]) | A.LetIn (var, s, t) -> Box.V(map_attributes attr, (make_def "let" var s "in")@[ast2box t]) | A.LetRec (_, vars, body) -> let definitions = let rec make_defs let_txt = function [] -> [] | [(var,s,_)] -> make_def let_txt var s "in" | (var,s,_)::tl -> (make_def let_txt var s "")@(make_defs "and" tl) in make_defs "let rec" vars in Box.V(map_attributes attr, definitions@[ast2box body]) | A.Ident (s, subst) -> let subst = let rec make_substs start_txt = function [] -> [] | [(s,t)] -> make_subst start_txt s t "]" | (s,t)::tl -> (make_subst start_txt s t ";")@(make_substs " " tl) in make_substs "[" subst in Box.V([], (* attr here or on Vbox? *) [Box.Text(map_attributes attr,s); Box.indent(Box.V([],subst))]) | A.Implicit -> Box.Text([],"_") (* big? *) | A.Meta (n, l) -> let local_context = List.map (function t -> Box.H([],[aux_option t; Box.Text([],";")])) l in Box.V(map_attributes attr, [Box.Text([],"?"^(string_of_int n)); Box.H([],[Box.Text([],"["); Box.V([],local_context); Box.Text([],"]")])]) | A.Num (s, _) -> Box.Text([],s) | A.Sort kind -> (match kind with `Prop -> Box.Text([],"Prop") | `Set -> Box.Text([],"Set") | `Type -> Box.Text([],"Type") | `CProp -> Box.Text([],"CProp")) | A.Symbol (s, _) -> Box.Text([],s) and aux_option = function None -> Box.Text([],"_") | Some ast -> ast2box ast and make_var = function (Cic.Anonymous, None) -> Box.Text([],"_:_") | (Cic.Anonymous, Some t) -> Box.H([],[Box.Text([],"_:");ast2box t]) | (Cic.Name s, None) -> Box.Text([],s) | (Cic.Name s, Some t) -> if is_big t then Box.V([],[Box.Text([],s^":"); Box.indent(bigast2box t)]) else Box.H([],[Box.Text([],s^":");Box.Object([],t)]) and make_pattern constr = function [] -> Box.Text([],constr) | vars -> let bvars = List.fold_right (fun var acc -> let bv = match var with (* ignoring the type *) (Cic.Anonymous, _) -> Box.Text([],"_") | (Cic.Name s, _) -> Box.Text([],s) in Box.Text([]," ")::bv::acc) vars [Box.Text([],")")] in Box.H([],Box.Text([],"(")::Box.Text([],constr)::bvars) and make_def let_txt var def end_txt = let name = (match var with (* ignoring the type *) (Cic.Anonymous, _) -> Box.Text([],"_") | (Cic.Name s, _) -> Box.Text([],s)) in pretty_append [Box.Text([],let_txt); Box.smallskip; name; Box.smallskip; Box.Text([],"=") ] def [Box.smallskip;Box.Text([],end_txt)] and make_subst start_txt varname body end_txt = pretty_append [Box.Text([],start_txt); Box.Text([],varname); Box.smallskip; Box.Text([],":=") ] body [Box.Text([],end_txt)] and pretty_append l ast tail = if is_big ast then [Box.H([],l); Box.H([],Box.skip::(bigast2box ast)::tail)] else [Box.H([],l@(Box.smallskip::(ast2box ast)::tail))] ;;