Annotation of researchv10no/cmd/sml/lib/twig/runtime.sml, revision 1.1.1.1

1.1       root        1: 
                      2: (* April 1989, Jussi Rintanen, Helsinki University of Technology *)
                      3: 
                      4: (* This is the signature of a specification generated by ML-Twig *)
                      5: 
                      6: signature TWIG_SPECIFICATION =
                      7:   sig
                      8:     type cost and tree and result
                      9:     eqtype rule and symbol
                     10: 
                     11:     val get_subtrees : tree -> tree list
                     12:     val node_value : tree -> symbol
                     13:     val cost_less : cost * cost -> bool
                     14: 
                     15:     datatype skeletal = Skeleton of rule * cost * tree * skeletal list
                     16: 
                     17:     exception MatchAbort and InternalError of string
                     18: 
                     19:     val execute_cost : rule * tree * skeletal list -> cost
                     20:     val execute : skeletal -> result
                     21:     val getreplacement : result -> tree
                     22:     val rewriterule : rule -> bool
                     23:     val matches : rule -> int
                     24: 
                     25: (* Definitions for unit rule matches and the tree pattern matching automaton *)
                     26: 
                     27:     eqtype state
                     28: 
                     29:     datatype matchtree = Chain of rule * symbol * matchtree list
                     30:     val unitmatches : symbol -> matchtree list
                     31: 
                     32:     val childsymbol : int -> symbol
                     33:     val initialstate : state
                     34:     val go : state * symbol -> state
                     35:     val go_f : state * symbol -> (int * rule * symbol) list
                     36: end;
                     37: 
                     38: (* This functor maps a specification to a structure containing a complete tree
                     39:    processor program and associated definitions. *)
                     40: 
                     41: functor MAKEtreeprocessor ( Specification : TWIG_SPECIFICATION) =
                     42:   struct
                     43:     structure Spec : TWIG_SPECIFICATION = Specification
                     44: 
                     45:     open Spec
                     46: 
                     47:     exception NoCover
                     48:     
                     49:     fun internal s = raise InternalError ("FATAL:"^s)
                     50: 
                     51: (* The structure representation implements a data type for
                     52:    maintaining information of the matching tree pattern
                     53:    matching process. The actual implementation is left
                     54:    unspecified in the signature. However, because of the
                     55:    match mode rewrite, an implementation without side effects
                     56:    is required. *)
                     57: 
                     58:     structure Representation :
                     59:       sig
                     60:        type 's table
                     61:        structure Spec : TWIG_SPECIFICATION
                     62: 
                     63:        val empty_table : unit -> 's table
                     64:        val new_level : 's table -> 's table
                     65:        val contribute0 : 's table * int * Spec.rule * Spec.symbol -> 's table
                     66:        val contribute1 : 's table * int * Spec.rule * Spec.symbol * 's -> 's table
                     67:        val get_level : 's table -> (Spec.symbol * (Spec.rule * int * 's list) list) list * 's table
                     68:       end
                     69:     =
                     70:     struct
                     71: 
                     72: (* The table is a list, where the head contains the match information
                     73:    for the current node of the user tree. The tail of the list
                     74:    contains the match information for the ancestors of the current
                     75:    node. The match information for a node is an ordered list of pairs,
                     76:    where the first member is the number of the non-terminal, to which
                     77:    the matches in the second member contribute.
                     78:      The matches for a non-terminal are in an ordered list of triples
                     79:    rule * number of matches * children skeletons. *)
                     80: 
                     81:       structure Spec = Spec
                     82: 
                     83:       open Spec
                     84: 
                     85:       type 's table = (symbol * (rule * int * 's list) list) list list
                     86:       fun empty_table () = []
                     87:       fun new_level l = []::l
                     88:       fun insert0' (r:rule,nil) = [(r,1,[])]
                     89:        | insert0' (r:rule,(h as (r',m',s'))::hs) =
                     90:          if r' <> r
                     91:            then h :: insert0' (r,hs)
                     92:          else (r,m'+1,s')::hs
                     93:       fun insert0 (nil,r,t:symbol) = [(t,[(r,1,[])])]
                     94:        | insert0 ((h as (t',a))::hs,r,t) =
                     95:          if t' <> t
                     96:            then h :: insert0 (hs,r,t)
                     97:          else (t,insert0' (r,a))::hs
                     98:       fun insert1' (r:rule,s,nil) = [(r,1,[s])]
                     99:        | insert1' (r,s,(h as (r',m',s'))::hs) =
                    100:          if r' <> r
                    101:            then h :: insert1' (r,s,hs)
                    102:          else (r,m'+1,s::s')::hs
                    103:       fun insert1 (nil,r,t:symbol,s) = [(t,[(r,1,[s])])]
                    104:        | insert1 ((h as (t',a))::hs,r,t,s) =
                    105:          if t' <> t
                    106:            then h :: insert1 (hs,r,t,s)
                    107:          else (t,insert1' (r,s,a)):: hs
                    108:       fun contribute0 (a::l,1,r,t) = insert0 (a,r,t) :: l
                    109:        | contribute0 (a::l,n,r,t) = a::contribute0(l,n-1,r,t)
                    110:        | contribute0 _ = internal "run out of levels"
                    111:       fun contribute1 (a::l,1,r,t,s) = insert1(a,r,t,s) :: l
                    112:         | contribute1 (a::l,n,r,t,s) = a::contribute1(l,n-1,r,t,s)
                    113:        | contribute1 _ = internal "run out of levels"
                    114:       fun get_level (a::l) = (a,l)
                    115:        | get_level _ = internal "run out of levels"
                    116:     end
                    117: 
                    118:   open Representation
                    119: 
                    120: (* Utility functions *)
                    121: 
                    122:   val accum = revfold
                    123: 
                    124:   fun cost (Skeleton(_,c,_,_)) = c
                    125:     
                    126:   fun insert (i:symbol, s, nil) = [(i,s)]
                    127:     | insert (i, s, (head as (i',s'))::rest) =
                    128:          if i = i'
                    129:            then
                    130:              if cost_less (cost s,cost s')
                    131:                then (i,s)::rest
                    132:              else head::rest
                    133:          else head :: (insert (i,s,rest))
                    134: 
                    135:   fun build_skeleton (ar as (r,t,cs)) = Skeleton (r,execute_cost ar,t,rev cs)
                    136: 
                    137: (* get_closure takes four arguments. The first is a unit rule tree.
                    138: The second is the sub-skeleton in the unit rule match. The third
                    139: is the ir-tree of the current node, and the fourth is the list
                    140: of skeletons generated so far. The skeleton list consists of pairs:
                    141: the first element is the number of the non-terminal of the rule,
                    142: and the second element is the skeleton. *)
                    143: 
                    144:   fun get_closure (ct,ss,t,ac) =
                    145:     accum (fn (Chain(r,n,cs),ac') =>
                    146:           let val skel = build_skeleton(r,t,ss)
                    147:           in
                    148:             get_closure (cs,[skel],t,insert (n,skel,ac'))
                    149:           end handle MatchAbort => ac')
                    150:           ct ac
                    151: 
                    152:   fun someone (t,still_best, nil) = [still_best]
                    153:     | someone (t,still_best, (r,m,cs)::rest) =
                    154:       if matches r = m
                    155:        then
                    156:          let val skel = build_skeleton (r,t,cs)
                    157:          in someone (t,if cost_less (cost skel,cost still_best)
                    158:                        then skel
                    159:                      else still_best,rest)
                    160:          end handle MatchAbort => someone (t,still_best,rest)
                    161:        else someone(t,still_best,rest)
                    162: 
                    163:   fun still_no_one (t,nil) = nil
                    164:     | still_no_one (t,(r,m,cs)::rest) =
                    165:       if matches r = m
                    166:        then someone (t,build_skeleton (r,t,cs),rest)
                    167:          handle MatchAbort => still_no_one (t,rest)
                    168:       else still_no_one (t,rest)
                    169: 
                    170:   fun leave_best_alone (t,nil) = internal "matcher state inconsistent. lba."
                    171:     | leave_best_alone (t,l) = still_no_one (t,l)
                    172: 
                    173:   fun skeletons_of (state,node,tab) =
                    174:     let val (t,s) =
                    175:       case get_subtrees node of
                    176:        nil =>
                    177:          let val tab' =
                    178:            accum (fn ((h,r,n),t) => contribute0 (t,h-1,r,n))
                    179:              (go_f(state, node_value node)) tab
                    180:          in
                    181:            (tab', get_closure ((unitmatches o node_value) node,[],node,[]))
                    182:          end
                    183:       | ls =>
                    184:          let val state' = go (state, node_value node)
                    185:            val (table, _) =
                    186:              accum (fn (l,(t,i)) =>
                    187:                     let val state'' = go (state',childsymbol i)
                    188:                       val (t', ss) = skeletons_of (state'',l,t)
                    189:                     in (accum (fn ((r,s),t'') =>
                    190:                                let val finals = go_f (state'',r)
                    191:                                in
                    192:                                  accum
                    193:                                  (fn ((h,r,n),t''') =>
                    194:                                     contribute1 (t''',h-1,r,n,s))
                    195:                                     finals t''
                    196:                                end) ss t',i+1)
                    197:                     end)
                    198:                     ls
                    199:                     (new_level tab, 1)
                    200:            val (toplevel, table') = get_level table
                    201:          in
                    202:            (table',
                    203:             let val unclosurized = accum (fn ((_,nil),l) => l | ((n,[e]),l) => (n,e)::l | _ => internal "inconsistency. 01l")
                    204:               (map (fn (n,sl) => (n,leave_best_alone (node,sl))) toplevel)
                    205:                  nil
                    206:             in
                    207:               accum (fn ((n,s),al) =>
                    208:                      get_closure (unitmatches n,[s],node,al)) unclosurized unclosurized
                    209:             end)
                    210:          end
                    211:     in
                    212:       case s of
                    213:        [] => (t,[])
                    214:       | [(_,S as Skeleton(r,_,_,_))] =>
                    215:          if rewriterule r
                    216:            then skeletons_of(state,(getreplacement o execute) S,tab)
                    217:          else (t,s)
                    218:       |  (_,sk)::rest =>
                    219:            let val best as Skeleton (r,_,_,_) =
                    220:              accum (fn ((n,s),bs) =>
                    221:                     if cost_less (cost s,cost bs) then s else bs) rest sk
                    222:            in
                    223:              if rewriterule r
                    224:                then skeletons_of(state,
                    225:                                  (getreplacement o execute) best,
                    226:                                   tab)
                    227:              else (t,s)
                    228:            end
                    229:     end
                    230: 
                    231:   fun translate t = execute
                    232:     (case (skeletons_of (initialstate,t,empty_table())) of
                    233:        (_,(_,s)::t) =>
                    234:          accum (fn ((n,s),bs) =>
                    235:                 if cost_less (cost s,cost bs) then s else bs) t s
                    236:     | (_,nil) => raise NoCover)
                    237: 
                    238:   end;

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.