Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quellcode-Bibliothek

© Kompilation durch diese Firma

[Weder Korrektheit noch Funktionsfähigkeit der Software werden zugesichert.]

Datei: walks.prf   Sprache: SML

Original von: Isabelle©

(*  Title:      Pure/envir.ML
    Author:     Lawrence C Paulson, Cambridge University Computer Laboratory

Free-form environments.  The type of a term variable / sort of a type variable is
part of its name.  The lookup function must apply type substitutions,
since they may change the identity of a variable.
*)


signature ENVIR =
sig
  type tenv = (typ * term) Vartab.table
  datatype env = Envir of {maxidx: int, tenv: tenv, tyenv: Type.tyenv}
  val maxidx_of: env -> int
  val term_env: env -> tenv
  val type_env: env -> Type.tyenv
  val is_empty: env -> bool
  val empty: int -> env
  val init: env
  val merge: env * env -> env
  val insert_sorts: env -> sort list -> sort list
  val genvars: string -> env * typ list -> env * term list
  val genvar: string -> env * typ -> env * term
  val lookup1: tenv -> indexname * typ -> term option
  val lookup: env -> indexname * typ -> term option
  val update: (indexname * typ) * term -> env -> env
  val above: env -> int -> bool
  val vupdate: (indexname * typ) * term -> env -> env
  val norm_type_same: Type.tyenv -> typ Same.operation
  val norm_types_same: Type.tyenv -> typ list Same.operation
  val norm_type: Type.tyenv -> typ -> typ
  val norm_term_same: env -> term Same.operation
  val norm_term: env -> term -> term
  val beta_norm: term -> term
  val head_norm: env -> term -> term
  val eta_long: typ list -> term -> term
  val eta_contract: term -> term
  val beta_eta_contract: term -> term
  val aeconv: term * term -> bool
  val body_type: env -> typ -> typ
  val binder_types: env -> typ -> typ list
  val strip_type: env -> typ -> typ list * typ
  val fastype: env -> typ list -> term -> typ
  val subst_type_same: Type.tyenv -> typ Same.operation
  val subst_term_types_same: Type.tyenv -> term Same.operation
  val subst_term_same: Type.tyenv * tenv -> term Same.operation
  val subst_type: Type.tyenv -> typ -> typ
  val subst_term_types: Type.tyenv -> term -> term
  val subst_term: Type.tyenv * tenv -> term -> term
  val expand_atom: typ -> typ * term -> term
  val expand_term: (term -> (typ * term) option) -> term -> term
  val expand_term_frees: ((string * typ) * term) list -> term -> term
end;

structure Envir: ENVIR =
struct

(** datatype env **)

(*Updating can destroy environment in 2 ways!
   (1) variables out of range
   (2) circular assignments
*)


type tenv = (typ * term) Vartab.table;

datatype env = Envir of
 {maxidx: int,          (*upper bound of maximum index of vars*)
  tenv: tenv,           (*assignments to Vars*)
  tyenv: Type.tyenv};   (*assignments to TVars*)

fun make_env (maxidx, tenv, tyenv) =
  Envir {maxidx = maxidx, tenv = tenv, tyenv = tyenv};

fun maxidx_of (Envir {maxidx, ...}) = maxidx;
fun term_env (Envir {tenv, ...}) = tenv;
fun type_env (Envir {tyenv, ...}) = tyenv;

fun is_empty env =
  Vartab.is_empty (term_env env) andalso
  Vartab.is_empty (type_env env);


(* build env *)

fun empty maxidx = make_env (maxidx, Vartab.empty, Vartab.empty);
val init = empty ~1;

fun merge
   (Envir {maxidx = maxidx1, tenv = tenv1, tyenv = tyenv1},
    Envir {maxidx = maxidx2, tenv = tenv2, tyenv = tyenv2}) =
  make_env (Int.max (maxidx1, maxidx2),
    Vartab.merge (op =) (tenv1, tenv2),
    Vartab.merge (op =) (tyenv1, tyenv2));


(*NB: type unification may invent new sorts*)  (* FIXME tenv!? *)
val insert_sorts = Vartab.fold (fn (_, (_, T)) => Sorts.insert_typ T) o type_env;

(*Generate a list of distinct variables.
  Increments index to make them distinct from ALL present variables. *)

fun genvars name (Envir {maxidx, tenv, tyenv}, Ts) : env * term list =
  let
    fun genvs (_, [] : typ list) : term list = []
      | genvs (_, [T]) = [Var ((name, maxidx + 1), T)]
      | genvs (n, T :: Ts) =
          Var ((name ^ radixstring (26, "a" , n), maxidx + 1), T)
            :: genvs (n + 1, Ts);
  in (Envir {maxidx = maxidx + 1, tenv = tenv, tyenv = tyenv}, genvs (0, Ts)) end;

(*Generate a variable.*)
fun genvar name (env, T) : env * term =
  let val (env', [v]) = genvars name (env, [T])
  in (env', v) end;

fun var_clash xi T T' =
  raise TYPE ("Variable has two distinct types", [], [Var (xi, T'), Var (xi, T)]);

fun lookup_check check tenv (xi, T) =
  (case Vartab.lookup tenv xi of
    NONE => NONE
  | SOME (U, t) => if check (T, U) then SOME t else var_clash xi T U);

(*When dealing with environments produced by matching instead
  of unification, there is no need to chase assigned TVars.
  In this case, we can simply ignore the type substitution
  and use = instead of eq_type.*)

fun lookup1 tenv = lookup_check (op =) tenv;

fun lookup (Envir {tenv, tyenv, ...}) = lookup_check (Type.unified tyenv) tenv;

fun update ((xi, T), t) (Envir {maxidx, tenv, tyenv}) =
  Envir {maxidx = maxidx, tenv = Vartab.update_new (xi, (T, t)) tenv, tyenv = tyenv};

(*Determine if the least index updated exceeds lim*)
fun above (Envir {tenv, tyenv, ...}) lim =
  (case Vartab.min tenv of SOME ((_, i), _) => i > lim | NONE => true) andalso
  (case Vartab.min tyenv of SOME ((_, i), _) => i > lim | NONE => true);

(*Update, checking Var-Var assignments: try to suppress higher indexes*)
fun vupdate ((a, U), t) env =
  (case t of
    Var (nT as (name', T)) =>
      if a = name' then env (*cycle!*)
      else if Term_Ord.indexname_ord (a, name') = LESS then
        (case lookup env nT of  (*if already assigned, chase*)
          NONE => update (nT, Var (a, T)) env
        | SOME u => vupdate ((a, U), u) env)
      else update ((a, U), t) env
  | _ => update ((a, U), t) env);



(** beta normalization wrt. environment **)

(*Chases variables in env.  Does not exploit sharing of variable bindings
  Does not check types, so could loop.*)


local

fun norm_type0 tyenv : typ Same.operation =
  let
    fun norm (Type (a, Ts)) = Type (a, Same.map norm Ts)
      | norm (TFree _) = raise Same.SAME
      | norm (TVar v) =
          (case Type.lookup tyenv v of
            SOME U => Same.commit norm U
          | NONE => raise Same.SAME);
  in norm end;

fun norm_term1 tenv : term Same.operation =
  let
    fun norm (Var v) =
          (case lookup1 tenv v of
            SOME u => Same.commit norm u
          | NONE => raise Same.SAME)
      | norm (Abs (a, T, body)) = Abs (a, T, norm body)
      | norm (Abs (_, _, body) $ t) = Same.commit norm (subst_bound (t, body))
      | norm (f $ t) =
          ((case norm f of
             Abs (_, _, body) => Same.commit norm (subst_bound (t, body))
           | nf => nf $ Same.commit norm t)
          handle Same.SAME => f $ norm t)
      | norm _ = raise Same.SAME;
  in norm end;

fun norm_term2 (envir as Envir {tyenv, ...}) : term Same.operation =
  let
    val normT = norm_type0 tyenv;
    fun norm (Const (a, T)) = Const (a, normT T)
      | norm (Free (a, T)) = Free (a, normT T)
      | norm (Var (xi, T)) =
          (case lookup envir (xi, T) of
            SOME u => Same.commit norm u
          | NONE => Var (xi, normT T))
      | norm (Abs (a, T, body)) =
          (Abs (a, normT T, Same.commit norm body)
            handle Same.SAME => Abs (a, T, norm body))
      | norm (Abs (_, _, body) $ t) = Same.commit norm (subst_bound (t, body))
      | norm (f $ t) =
          ((case norm f of
             Abs (_, _, body) => Same.commit norm (subst_bound (t, body))
           | nf => nf $ Same.commit norm t)
          handle Same.SAME => f $ norm t)
      | norm _ = raise Same.SAME;
  in norm end;

in

fun norm_type_same tyenv T =
  if Vartab.is_empty tyenv then raise Same.SAME
  else norm_type0 tyenv T;

fun norm_types_same tyenv Ts =
  if Vartab.is_empty tyenv then raise Same.SAME
  else Same.map (norm_type0 tyenv) Ts;

fun norm_type tyenv T = norm_type_same tyenv T handle Same.SAME => T;

fun norm_term_same (envir as Envir {tenv, tyenv, ...}) =
  if Vartab.is_empty tyenv then norm_term1 tenv
  else norm_term2 envir;

fun norm_term envir t = norm_term_same envir t handle Same.SAME => t;

fun beta_norm t =
  if Term.could_beta_contract t then norm_term init t else t;

end;


(* head normal form for unification *)

fun head_norm env =
  let
    fun norm (Var v) =
        (case lookup env v of
          SOME u => head_norm env u
        | NONE => raise Same.SAME)
      | norm (Abs (a, T, body)) = Abs (a, T, norm body)
      | norm (Abs (_, _, body) $ t) = Same.commit norm (subst_bound (t, body))
      | norm (f $ t) =
          (case norm f of
            Abs (_, _, body) => Same.commit norm (subst_bound (t, body))
          | nf => nf $ t)
      | norm _ = raise Same.SAME;
  in Same.commit norm end;


(* eta-long beta-normal form *)

fun eta_long Ts (Abs (s, T, t)) = Abs (s, T, eta_long (T :: Ts) t)
  | eta_long Ts t =
      (case strip_comb t of
        (Abs _, _) => eta_long Ts (beta_norm t)
      | (u, ts) =>
          let
            val Us = binder_types (fastype_of1 (Ts, t));
            val i = length Us;
            val long = eta_long (rev Us @ Ts);
          in
            fold_rev (Term.abs o pair "x") Us
              (list_comb (incr_boundvars i u,
                map (long o incr_boundvars i) ts @ map (long o Bound) (i - 1 downto 0)))
          end);


(* full eta contraction *)

local

fun decr lev (Bound i) = if i >= lev then Bound (i - 1) else raise Same.SAME
  | decr lev (Abs (a, T, body)) = Abs (a, T, decr (lev + 1) body)
  | decr lev (t $ u) = (decr lev t $ decrh lev u handle Same.SAME => t $ decr lev u)
  | decr _ _ = raise Same.SAME
and decrh lev t = (decr lev t handle Same.SAME => t);

fun eta (Abs (a, T, body)) =
    ((case eta body of
        body' as (f $ Bound 0) =>
          if Term.is_dependent f then Abs (a, T, body')
          else decrh 0 f
     | body' => Abs (a, T, body')) handle Same.SAME =>
        (case body of
          f $ Bound 0 =>
            if Term.is_dependent f then raise Same.SAME
            else decrh 0 f
        | _ => raise Same.SAME))
  | eta (t $ u) = (eta t $ Same.commit eta u handle Same.SAME => t $ eta u)
  | eta _ = raise Same.SAME;

in

fun eta_contract t =
  if Term.could_eta_contract t then Same.commit eta t else t;

end;

val beta_eta_contract = eta_contract o beta_norm;

fun aeconv (t, u) = t aconv u orelse eta_contract t aconv eta_contract u;


fun body_type env (Type ("fun", [_, T])) = body_type env T
  | body_type env (T as TVar v) =
      (case Type.lookup (type_env env) v of
        NONE => T
      | SOME T' => body_type env T')
  | body_type _ T = T;

fun binder_types env (Type ("fun", [T, U])) = T :: binder_types env U
  | binder_types env (TVar v) =
      (case Type.lookup (type_env env) v of
        NONE => []
      | SOME T' => binder_types env T')
  | binder_types _ _ = [];

fun strip_type env T = (binder_types env T, body_type env T);

(*finds type of term without checking that combinations are consistent
  Ts holds types of bound variables*)

fun fastype (Envir {tyenv, ...}) =
  let
    val funerr = "fastype: expected function type";
    fun fast Ts (f $ u) =
          (case Type.devar tyenv (fast Ts f) of
            Type ("fun", [_, T]) => T
          | TVar _ => raise TERM (funerr, [f $ u])
          | _ => raise TERM (funerr, [f $ u]))
      | fast _ (Const (_, T)) = T
      | fast _ (Free (_, T)) = T
      | fast Ts (Bound i) =
          (nth Ts i handle General.Subscript => raise TERM ("fastype: Bound", [Bound i]))
      | fast _ (Var (_, T)) = T
      | fast Ts (Abs (_, T, u)) = T --> fast (T :: Ts) u;
  in fast end;


(** plain substitution -- without variable chasing **)

local

fun subst_type0 tyenv = Term_Subst.map_atypsT_same
  (fn TVar v =>
        (case Type.lookup tyenv v of
          SOME U => U
        | NONE => raise Same.SAME)
    | _ => raise Same.SAME);

fun subst_term1 tenv = Term_Subst.map_aterms_same
  (fn Var v =>
        (case lookup1 tenv v of
          SOME u => u
        | NONE => raise Same.SAME)
    | _ => raise Same.SAME);

fun subst_term2 tenv tyenv : term Same.operation =
  let
    val substT = subst_type0 tyenv;
    fun subst (Const (a, T)) = Const (a, substT T)
      | subst (Free (a, T)) = Free (a, substT T)
      | subst (Var (xi, T)) =
          (case lookup1 tenv (xi, T) of
            SOME u => u
          | NONE => Var (xi, substT T))
      | subst (Bound _) = raise Same.SAME
      | subst (Abs (a, T, t)) =
          (Abs (a, substT T, Same.commit subst t)
            handle Same.SAME => Abs (a, T, subst t))
      | subst (t $ u) = (subst t $ Same.commit subst u handle Same.SAME => t $ subst u);
  in subst end;

in

fun subst_type_same tyenv T =
  if Vartab.is_empty tyenv then raise Same.SAME
  else subst_type0 tyenv T;

fun subst_term_types_same tyenv t =
  if Vartab.is_empty tyenv then raise Same.SAME
  else Term_Subst.map_types_same (subst_type0 tyenv) t;

fun subst_term_same (tyenv, tenv) =
  if Vartab.is_empty tenv then subst_term_types_same tyenv
  else if Vartab.is_empty tyenv then subst_term1 tenv
  else subst_term2 tenv tyenv;

fun subst_type tyenv T = subst_type_same tyenv T handle Same.SAME => T;
fun subst_term_types tyenv t = subst_term_types_same tyenv t handle Same.SAME => t;
fun subst_term envs t = subst_term_same envs t handle Same.SAME => t;

end;



(** expand defined atoms -- with local beta reduction **)

fun expand_atom T (U, u) =
  subst_term_types (Type.raw_match (U, T) Vartab.empty) u
    handle Type.TYPE_MATCH => raise TYPE ("expand_atom: ill-typed replacement", [T, U], [u]);

fun expand_term get =
  let
    fun expand tm =
      let
        val (head, args) = Term.strip_comb tm;
        val args' = map expand args;
        fun comb head' = Term.list_comb (head', args');
      in
        (case head of
          Abs (x, T, t) => comb (Abs (x, T, expand t))
        | _ =>
          (case get head of
            SOME def => Term.betapplys (expand_atom (Term.fastype_of head) def, args')
          | NONE => comb head))
      end;
  in expand end;

fun expand_term_frees defs =
  let
    val eqs = map (fn ((x, U), u) => (x, (U, u))) defs;
    val get = fn Free (x, _) => AList.lookup (op =) eqs x | _ => NONE;
  in expand_term get end;

end;

¤ Dauer der Verarbeitung: 0.5 Sekunden  (vorverarbeitet)  ¤





Druckansicht
unsichere Verbindung
Druckansicht
sprechenden Kalenders

in der Quellcodebibliothek suchen




Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.


Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.


Bot Zugriff



                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik