(* ========================================================================= *) (* FIRST ORDER LOGIC TERMS *) (* Copyright (c) 2001 Joe Leslie-Hurd, distributed under the BSD License *) (* ========================================================================= *)
structure Term :> Term = struct
open Useful;
(* ------------------------------------------------------------------------- *) (* A type of first order logic terms. *) (* ------------------------------------------------------------------------- *)
type var = Name.name;
type functionName = Name.name;
type function = functionName * int;
typeconst = functionName;
datatype term =
Var of Name.name
| Fn of Name.name * term list;
fun destConst (Fn (c, [])) = c
| destConst _ = raise Error "destConst";
val isConst = can destConst;
(* Binary functions *)
fun mkBinop f (a,b) = Fn (f,[a,b]);
fun destBinop f (Fn (x,[a,b])) = if Name.equal x f then (a,b) elseraise Error "Term.destBinop: wrong binop"
| destBinop _ _ = raise Error "Term.destBinop: not a binop";
fun isBinop f = can (destBinop f);
(* ------------------------------------------------------------------------- *) (* The size of a term in symbols. *) (* ------------------------------------------------------------------------- *)
val VAR_SYMBOLS = 1;
val FN_SYMBOLS = 1;
local fun sz n [] = n
| sz n (Var _ :: tms) = sz (n + VAR_SYMBOLS) tms
| sz n (Fn (func,args) :: tms) = sz (n + FN_SYMBOLS) (args @ tms); in fun symbols tm = sz 0 [tm]; end;
(* ------------------------------------------------------------------------- *) (* A total comparison function for terms. *) (* ------------------------------------------------------------------------- *)
local fun cmp [] [] = EQUAL
| cmp (tm1 :: tms1) (tm2 :: tms2) = let val tm1_tm2 = (tm1,tm2) in if Portable.pointerEqual tm1_tm2 then cmp tms1 tms2 else case tm1_tm2 of
(Var v1, Var v2) =>
(case Name.compare (v1,v2) of
LESS => LESS
| EQUAL => cmp tms1 tms2
| GREATER => GREATER)
| (Var _, Fn _) => LESS
| (Fn _, Var _) => GREATER
| (Fn (f1,a1), Fn (f2,a2)) =>
(case Name.compare (f1,f2) of
LESS => LESS
| EQUAL =>
(case Int.compare (length a1, length a2) of
LESS => LESS
| EQUAL => cmp (a1 @ tms1) (a2 @ tms2)
| GREATER => GREATER)
| GREATER => GREATER) end
| cmp _ _ = raise Bug "Term.compare"; in fun compare (tm1,tm2) = cmp [tm1] [tm2]; end;
local fun subtms [] acc = acc
| subtms ((path,tm) :: rest) acc = let fun f (n,arg) = (n :: path, arg)
val acc = (List.rev path, tm) :: acc in case tm of
Var _ => subtms rest acc
| Fn (_,args) => subtms (List.map f (enumerate args) @ rest) acc end; in fun subterms tm = subtms [([],tm)] []; end;
fun replace tm ([],res) = if equal res tm then tm else res
| replace tm (h :: t, res) = case tm of
Var _ => raise Error "Term.replace: Var"
| Fn (func,tms) => if h >= length tms thenraise Error "Term.replace: Fn" else let val arg = List.nth (tms,h) val arg' = replace arg (t,res) in if Portable.pointerEqual (arg',arg) then tm else Fn (func, updateNth (h,arg') tms) end;
funfind pred = let fun search [] = NONE
| search ((path,tm) :: rest) = if pred tm then SOME (List.rev path) else case tm of
Var _ => search rest
| Fn (_,a) => let val subtms = List.map (fn (i,t) => (i :: path, t)) (enumerate a) in
search (subtms @ rest) end in
fn tm => search [([],tm)] end;
local fun free _ [] = false
| free v (Var w :: tms) = Name.equal v w orelse free v tms
| free v (Fn (_,args) :: tms) = free v (args @ tms); in fun freeIn v tm = free v [tm]; end;
local fun free vs [] = vs
| free vs (Var v :: tms) = free (NameSet.add vs v) tms
| free vs (Fn (_,args) :: tms) = free vs (args @ tms); in val freeVarsList = free NameSet.empty;
local fun avoid av n = NameSet.member n av; in fun variantPrime av = Name.variantPrime {avoid = avoid av};
fun variantNum av = Name.variantNum {avoid = avoid av}; end;
(* ------------------------------------------------------------------------- *) (* Special support for terms with type annotations. *) (* ------------------------------------------------------------------------- *)
val hasTypeFunctionName = Name.fromString ":";
val hasTypeFunction = (hasTypeFunctionName,2);
fun destFnHasType ((f,a) : functionName * term list) = ifnot (Name.equal f hasTypeFunctionName) then raise Error "Term.destFnHasType" else case a of
[tm,ty] => (tm,ty)
| _ => raise Error "Term.destFnHasType";
val isFnHasType = can destFnHasType;
fun isTypedVar tm = case tm of
Var _ => true
| Fn func => case total destFnHasType func of
SOME (Var _, _) => true
| _ => false;
local fun sz n [] = n
| sz n (tm :: tms) = case tm of
Var _ => sz (n + 1) tms
| Fn func => case total destFnHasType func of
SOME (tm,_) => sz n (tm :: tms)
| NONE => let val (_,a) = func in
sz (n + 1) (a @ tms) end; in fun typedSymbols tm = sz 0 [tm]; end;
local fun subtms [] acc = acc
| subtms ((path,tm) :: rest) acc = case tm of
Var _ => subtms rest acc
| Fn func => case total destFnHasType func of
SOME (t,_) =>
(case t of
Var _ => subtms rest acc
| Fn _ => let val acc = (List.rev path, tm) :: acc val rest = (0 :: path, t) :: rest in
subtms rest acc end)
| NONE => let fun f (n,arg) = (n :: path, arg)
val (_,args) = func
val acc = (List.rev path, tm) :: acc
val rest = List.map f (enumerate args) @ rest in
subtms rest acc end; in fun nonVarTypedSubterms tm = subtms [([],tm)] []; end;
(* ------------------------------------------------------------------------- *) (* Special support for terms with an explicit function application operator. *) (* ------------------------------------------------------------------------- *)
val appName = Name.fromString ".";
fun mkFnApp (fTm,aTm) = (appName, [fTm,aTm]);
fun mkApp f_a = Fn (mkFnApp f_a);
fun destFnApp ((f,a) : Name.name * term list) = ifnot (Name.equal f appName) thenraise Error "Term.destFnApp" else case a of
[fTm,aTm] => (fTm,aTm)
| _ => raise Error "Term.destFnApp";
val isFnApp = can destFnApp;
fun destApp tm = case tm of
Var _ => raise Error "Term.destApp"
| Fn func => destFnApp func;
val isApp = can destApp;
fun listMkApp (f,l) = List.foldl mkApp f l;
local fun strip tms tm = case total destApp tm of
SOME (f,a) => strip (a :: tms) f
| NONE => (tm,tms); in fun stripApp tm = strip [] tm; end;
fun checkVarName bv n = let
val s = Name.toString n in if vName bv s then s else"$" ^ s end
fun varName bv = Print.ppMap (checkVarName bv) Print.ppString
fun checkFunctionName bv n = let
val s = Name.toString n in if StringSet.member s specialTokens orelse vName bv s then "(" ^ s ^ ")" else
s end
fun functionName bv = Print.ppMap (checkFunctionName bv) Print.ppString
fun stripNeg tm =
case tm of
Fn (f,[a]) => if Name.toString f <> neg then (0,tm) elselet val (n,tm) = stripNeg a in (n + 1, tm) end
| _ => (0,tm)
val destQuant = let
fun dest q (Fn (q', [Var v, body])) = if Name.toString q' <> q then NONE else
(case dest q body of
NONE => SOME (q,v,[],body)
| SOME (_,v',vs,body) => SOME (q, v, v' :: vs, body))
| dest _ _ = NONE in
fn tm => Useful.first (fn q => dest q tm) quants end
fun isQuant tm = Option.isSome (destQuant tm)
fun destBrack (Fn (b,[tm])) = let
val s = Name.toString b in
case List.find (fn (n,_,_) => n = s) bMap of
NONE => NONE
| SOME (_,b1,b2) => SOME (b1,tm,b2) end
| destBrack _ = NONE
fun isBrack tm = Option.isSome (destBrack tm)
fun functionArgument bv tm =
Print.sequence
Print.break
(if isBrack tm then customBracket bv tm elseif isVar tm orelse isConst tm then basic bv tm else bracket bv tm)
and basic bv (Var v) = varName bv v
| basic bv (Fn (f,args)) =
Print.inconsistentBlock 2
(functionName bv f :: List.map (functionArgument bv) args)
and customBracket bv tm =
case destBrack tm of
SOME (b1,tm,b2) => Print.ppBracket b1 b2 (term bv) tm
| NONE => basic bv tm
and innerQuant bv tm =
case destQuant tm of
NONE => term bv tm
| SOME (q,v,vs,tm) => let
val bv = StringSet.addList bv (List.map Name.toString (v :: vs)) in
Print.program
[Print.ppString q,
varName bv v,
Print.program
(List.map (Print.sequence Print.break o varName bv) vs),
Print.ppString ".",
Print.break,
innerQuant bv tm] end
and quantifier bv tm = ifnot (isQuant tm) then customBracket bv tm else Print.inconsistentBlock 2 [innerQuant bv tm]
and molecule bv (tm,r) = let
val (n,tm) = stripNeg tm in
Print.inconsistentBlock n
[Print.duplicate n (Print.ppString neg), if isI tm orelse (r andalso isQuant tm) then bracket bv tm else quantifier bv tm] end
and term bv tm = iPrinter (molecule bv) (tm,false)
and bracket bv tm = Print.ppBracket "("")" (term bv) tm in
term StringSet.empty end inputTerm;
val toString = Print.toString pp;
(* Parsing *)
local
open Parse;
infixr 9 >>++
infixr 8 ++
infixr 7 >>
infixr 6 ||
val isAlphaNum = let
val alphaNumChars = String.explode "_'" in
fn c => mem c alphaNumChars orelse Char.isAlphaNum c end;
local
val alphaNumToken = atLeastOne (some isAlphaNum) >> String.implode;
val symbolToken = let
fun isNeg c = str c = !negation
val symbolChars = String.explode "<>=-*+/\\?@|!$%^:;~"
fun isSymbol c = mem c symbolChars
fun isNonNegSymbol c = not (isNeg c) andalso isSymbol c in
some isNeg >> str ||
(some isNonNegSymbol ++ many (some isSymbol)) >>
(String.implode o op::) end;
val punctToken = let
val punctChars = String.explode "()[]{}.,"
fun isPunct c = mem c punctChars in
some isPunct >> str end;
val lexToken = alphaNumToken || symbolToken || punctToken;
val space = many (some Char.isSpace); in
val lexer = (space ++ lexToken ++ space) >> (fn (_,(tok,_)) => tok); end;
fun termParser inputStream = let
val quants = !binders and iOps = !infixes and neg = !negation and bracks = ("(",")") :: !brackets
fun varName bv =
some (vName bv) ||
(some (Useful.equal "$") ++ some possibleVarName) >> snd
fun fName bv s = not (StringSet.member s specialTokens) andalso not (vName bv s)
fun functionName bv =
some (fName bv) ||
(some (Useful.equal "(") ++ any ++ some (Useful.equal ")")) >>
(fn (_,(s,_)) => s)
fun basic bv tokens = let
val var = varName bv >> (Var o Name.fromString)
val const =
functionName bv >> (fn f => Fn (Name.fromString f, []))
fun bracket (ab,a,b) =
(some (Useful.equal a) ++ term bv ++ some (Useful.equal b)) >>
(fn (_,(tm,_)) => if ab = "()"then tm else Fn (Name.fromString ab, [tm]))
fun quantifier q = let
fun bind (v,t) =
Fn (Name.fromString q, [Var (Name.fromString v), t]) in
(some (Useful.equal q) ++
atLeastOne (some possibleVarName) ++
some (Useful.equal ".")) >>++
(fn (_,(vs,_)) =>
term (StringSet.addList bv vs) >>
(fn body => List.foldr bind body vs)) end in
var ||
const ||
first (List.map bracket bracks) ||
first (List.map quantifier quants) end tokens
and molecule bv tokens = let
val negations = many (some (Useful.equal neg)) >> length
val function =
(functionName bv ++ many (basic bv)) >>
(fn (f,args) => Fn (Name.fromString f, args)) ||
basic bv in
(negations ++ function) >>
(fn (n,tm) => funpow n (fn t => Fn (Name.fromString neg, [t])) tm) end tokens
and term bv tokens = iParser (molecule bv) tokens in
term StringSet.empty end inputStream; in
fun fromString input = let
val chars = Stream.fromList (String.explode input)
val tokens = everything (lexer >> singleton) chars
val terms = everything (termParser >> singleton) tokens in
case Stream.toList terms of
[tm] => tm
| _ => raise Error"Term.fromString" end; end;
local
val antiquotedTermToString =
Print.toString (Print.ppBracket "("")" pp); in
val parse = Parse.parseQuotation antiquotedTermToString fromString; end;
end
structure TermOrdered = struct type t = Term.term val compare = Term.compare end
structure TermMap = KeyMap (TermOrdered);
structure TermSet = ElementSet (TermMap);
¤ 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.0.15Bemerkung:
¤
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.