implementation module cli // $Id$ import law import coreclean import strat import absmodule import rule import dnc import basic from syntax import SK_Function import general import StdEnv /* cli.lit - Clean implementation modules ====================================== Description ----------- This script implements Clean modules (type module) and partial Clean programs (type cli), which are essentially sets of Clean modules. ------------------------------------------------------------ Interface --------- Exported identifiers: > %export > cli > readcli > loadclis > exports > typerule > imports > clistrategy > constrs > complete > showcli > printcli > aliases > macros > stripexports > printalgebra Required types: identifier - type@source.lit type@source.lit ... ------------------------------------------------------------ Includes -------- > %include "dnc.lit" > %include "../src/basic.lit" > %include "../src/pfun.lit" > %include "../src/graph.lit" > %include "../src/rule.lit" > %include "../src/spine.lit" > %include "strat.lit" > %include "law.lit" > %include "../src/clean.lit" > %include "../src/module.lit" ------------------------------------------------------------ Implementation -------------- Implementation of identifier identifier :: type identifierone arguments = body ... ------------------------------------------------------------------------ Abstype implementation. > abstype cli > with readcli :: [char] -> cli > loadclis :: [[char]] -> cli > exports :: cli -> [symbol] > typerule :: cli -> symbol -> rule typesymbol typenode > rules :: cli -> symbol -> optional [rule symbol node] > imports :: cli -> [symbol] > clistrategy :: cli -> (graph symbol node->node->**->bool) -> strategy symbol ** node **** > constrs :: cli -> [(typesymbol,[symbol])] > complete :: cli -> [symbol] -> bool > showcli :: cli -> [char] > aliases :: cli -> [(typesymbol,rule typesymbol typenode)] > macros :: cli -> [(symbol,rule symbol node)] > stripexports :: [char] -> cli -> cli */ :: Cli = CliAlias (SuclSymbol->String) (Module SuclSymbol SuclVariable SuclTypeSymbol SuclTypeVariable) /* > cli == module symbol node typesymbol typenode > readcli = compilecli.readcleanparts > loadclis > = compilecli.concat.map readcleanparts > stripexports main (tdefs,(es,as,ts,rs)) = (tdefs,([User m i|User m i<-es;m=main],as,ts,rs)) > exports (tdefs,(es,as,ts,rs)) = es */ exports :: Cli -> [SuclSymbol] exports (CliAlias ss m) = m.exportedsymbols // Determine the arity of a core clean symbol arity :: Cli SuclSymbol -> Int arity (CliAlias ss m) sym = extendfn m.arities (length o arguments o (extendfn m.typerules (coretyperule--->"coreclean.coretyperule begins from cli.arity"))) sym /* > typerule (tdefs,(es,as,ts,rs)) = maxtyperule ts */ typerule :: Cli SuclSymbol -> Rule SuclTypeSymbol SuclTypeVariable typerule (CliAlias ss m) sym = maxtyperule m.typerules sym /* > rules (tdefs,(es,as,ts,rs)) = foldmap Present Absent rs > imports (tdefs,(es,as,ts,rs)) = [sym|(sym,tdef)<-ts;~member (map fst rs) sym] > aliases ((tes,tas,tcs),defs) = tas > macros (tdefs,(es,as,ts,rs)) = as > clistrategy ((tes,tas,tcs),(es,as,ts,rs)) matchable > = ( checktype (maxtypeinfo ts). || Checks curried occurrences and strict arguments > checklaws cleanlaws. || Checks for special (hard coded) rules (+x0=x /y1=y ...) > checkrules matchable (foldmap id [] rs). > || Checks normal rewrite rules > checkimport islocal. || Checks for delta symbols > checkconstr (member (concat (map snd tcs))) > || Checks for constructors > ) (corestrategy matchable) || Checks rules for symbols in the language core (IF, _AP, ...) > where islocal (User m i) = member (map fst rs) (User m i) > islocal rsym = True || Symbols in the language core are always completely known */ clistrategy :: Cli ((Graph SuclSymbol SuclVariable) SuclVariable var -> Bool) -> Strategy SuclSymbol var SuclVariable answer | == var clistrategy (CliAlias showsymbol {arities=as,typeconstructors=tcs,typerules=ts,rules=rs}) matchable = ( checkarity getarity // Checks curried occurrences and strict arguments o checklaws cleanlaws // Checks for special (hard coded) rules (+x0=x /y1=y ...) o checkrules matchable (foldmap id [] rs) // Checks normal rewrite rules o checkimport islocal // Checks for delta symbols o ( checkconstr toString (flip isMember (flatten (map snd tcs))) // Checks for constructors ---> ("cli.clistrategy.checkconstr",tcs) ) ) (corestrategy matchable) // Checks rules for symbols in the language core (IF, _AP, ...) where islocal rsym=:(SuclUser (SK_Function _)) = isMember rsym (map fst rs) // User-defined function symbols can be imported, so they're known if we have a list of rules for them islocal _ = True // Symbols in the language core (the rest) are always completely known // This includes lifted case symbols; we lifted them ourselves, after all getarity sym = (arity <--- ("cli.clistrategy.getarity ends with "+++toString arity)) ---> ("cli.clistrategy.getarity begins for "+++showsymbol sym) where arity = extendfn as (typearity o (maxtyperule--->"cli.clistrategy.getarity uses maxtyperule") ts) sym typearity :: (Rule SuclTypeSymbol SuclTypeVariable) -> Int typearity ti = length (arguments ti) //maxtypeinfo :: [(SuclSymbol,(Rule SuclTypeSymbol SuclTypeVariable,[Bool]))] SuclSymbol -> (Rule SuclTypeSymbol SuclTypeVariable,[Bool]) //maxtypeinfo defs sym = extendfn defs coretypeinfo sym maxtyperule :: [(SuclSymbol,Rule SuclTypeSymbol SuclTypeVariable)] SuclSymbol -> Rule SuclTypeSymbol SuclTypeVariable maxtyperule defs sym = extendfn defs (coretyperule--->"cli.coretyperule begins from cli.maxtyperule") sym maxstricts :: [(SuclSymbol,[Bool])] SuclSymbol -> [Bool] maxstricts defs sym = extendfn defs corestricts sym /* > constrs ((tes,tas,tcs),defs) = tcs > complete ((tes,tas,tcs),(es,as,ts,rs)) = mkclicomplete tcs (fst.maxtypeinfo ts) */ complete :: Cli -> [SuclSymbol] -> Bool complete (CliAlias ss m) = mkclicomplete m.typeconstructors (maxtyperule m.typerules) /* > showcli = printcli > mkclicomplete > :: [(typesymbol,[symbol])] -> > (symbol->rule typesymbol *****) -> > [symbol] -> > bool > mkclicomplete tcs typerule [] = False > mkclicomplete tcs typerule syms > = False, if ~tdef > = foldmap superset (corecomplete tsym) tcs tsym syms, otherwise > where trule = typerule (hd syms) > (tdef,(tsym,targs)) = dnc (const "in mkclicomplete") (rulegraph trule) (rhs trule) */ mkclicomplete :: [(SuclTypeSymbol,[SuclSymbol])] (SuclSymbol->Rule SuclTypeSymbol tvar) [SuclSymbol] -> Bool | == tvar mkclicomplete tcs typerule [] = False mkclicomplete tcs typerule syms | not tdef = False = foldmap superset (corecomplete tsym) tcs tsym syms where trule = typerule (hd syms) (tdef,(tsym,_)) = dnc (const "in mkclicomplete") (rulegraph trule) (ruleroot trule) /* ------------------------------------------------------------------------ > printcli :: module symbol node typesymbol typenode -> [char] > printcli ((tes,tas,tcs),(es,as,ts,rs)) > = lay > ( (implementation++"MODULE "++thismodule++";"): > "": > "<< EXPORT": > map cleandef es++ > ">>": > "": > map showimport (partition fst snd (itypesyms++isyms))++ > concat (map cleanalg tcs)++ > concat (map cleanimp [(sym,plookup showsymbol ts sym,rules)|(sym,rules)<-rs;usersym sym]) > ) > where cleandef sym = " "++cleantyperule sym (maxtypeinfo ts sym) > cleanalg constr > = ["","TYPE",printalgebra (fst.maxtypeinfo ts) constr], if typesymbolmodule (fst constr)=Present thismodule > = [], otherwise > cleanimp (sym,tinfo,rules) > = prepend (trulelines++concat (map (cleanrule sym) rules)) > where trulelines > = [], if member (concat (map snd tcs)) sym > = [cleantyperule sym tinfo], otherwise > prepend [] = [] > prepend lines = "":"RULE":lines > implementation > = "", if showsymbol (hd es)="Start" > = "IMPLEMENTATION ", otherwise > isyms = [(module,ident)|((User module ident),tinfo)<-ts;~member (map fst rs) (User module ident)] > itypesyms > = foldr add [] tcs > where add (USER module ident,constrs) rest > = (module,ident):foldr addc rest constrs, if module~=thismodule > add typesymbol = id > addc (User module ident) rest > = (module,ident):rest > addc symbol = id > thismodule = foldoptional undef id (symbolmodule (hd es)) > showimport :: ([char],[[char]]) -> [char] > showimport (module,idents) = "FROM "++module++" IMPORT "++join ',' idents++";" > printalgebra :: (symbol->rule typesymbol typenode) -> (typesymbol,[symbol]) -> [char] > printalgebra typerule (tsym,syms) > = ":: "++ > showtypesymbol tsym++ > concat (map ((' ':).showtypenode) trargs)++ > concat (map2 (++) (" -> ":repeat " | ") alts)++ > ";" > where symtrules = map (pairwith typerule) syms > trule = snd (hd symtrules) > trroot = rhs trule > (trdef,trcont) = dnc (const "in printalgebra") (rulegraph trule) trroot > (trsym,trargs) > = trcont, if trdef > = (notrsym,notrargs), otherwise > notrsym = error ("printalgebra: no type symbol for typenode "++showtypenode trroot) > notrargs = error ("printalgebra: no type arguments for typenode "++showtypenode trroot) > alts = map (printalt trargs) symtrules > printalt :: [typenode] -> (symbol,rule typesymbol typenode) -> [char] > printalt trargs' (sym,trule) > = showsymbol sym++concat (map (' ':) (printgraph showtypesymbol showtypenode tgraph' targs')) > where targs = lhs trule; troot = rhs trule; tgraph = rulegraph trule > (trdef,(trsym,trargs)) = dnc (const "in printalt") tgraph troot > tnodes = trargs++(nodelist tgraph targs--trargs) > tnodes' = trargs'++(typeheap--trargs') > redirection = foldr (uncurry adjust) noredir (zip2 tnodes tnodes') > noredir tnode = error ("printalt: no redirection for typenode "++showtypenode tnode) > targs' = map redirection targs > tgraph' = movegraph redirection tnodes tgraph Compiling clean parts into module information... > compilecli > :: [cleanpart] -> > module symbol node typesymbol typenode > compilecli parts > = ((typeexports,aliases,typedefs),(exports,macros,typerules,locals)) > where typeexports = [tsym|Typeexport tsym<-parts] > aliases = [(tsym,compilerule targs troot tnodedefs)|Alias tsym targs troot tnodedefs<-parts] > typedefs = [(tsym,syms)|Algebra tsym syms<-parts] > exports = [sym|Export sym<-parts] > macros = [(sym,compilerule args root nodedefs)|Macro sym args root nodedefs<-parts] > typerules = [(sym,(compilerule targs troot tnodedefs,map (='!') stricts))|Type sym targs troot tnodedefs stricts<-parts] > locals = [(sym,rules sym)|Rules sym<-parts] > rules lsym = [compilerule args root nodedefs|Rule sym args root nodedefs<-parts;sym=lsym] > currytrule :: **** -> [*****] -> rule **** ***** -> rule **** ***** > currytrule fn theap trule > = mkrule ctargs ctroot ctgraph > where targs = lhs trule; troot = rhs trule; tgraph = rulegraph trule > ctargs = init targs > ctroot = hd (theap--nodelist tgraph (troot:targs)) > ctgraph = updategraph ctroot (fn,[last targs,troot]) tgraph */ mkcli :: (SuclSymbol->String) [(SuclSymbol,Rule SuclTypeSymbol SuclTypeVariable)] [(SuclSymbol,[Bool])] [SuclSymbol] [(SuclSymbol,Int)] [(SuclTypeSymbol,[(SuclSymbol,(Rule SuclTypeSymbol SuclTypeVariable,[Bool]))])] [(SuclSymbol,(Int,[Rule SuclSymbol SuclVariable]))] -> Cli mkcli showsymbol typerules stricts exports imports constrs bodies = CliAlias showsymbol { arities = map (mapsnd fst) bodies++imports , typeconstructors = map (mapsnd (map fst)) constrs , exportedsymbols = exports , typerules = typerules++flatten ((map (map (mapsnd fst) o snd)) constrs) , stricts = stricts++flatten ((map (map (mapsnd snd) o snd)) constrs) , rules = map (mapsnd snd) bodies } instance <<< Cli where (<<<) file (CliAlias showsymbol m) # file = file <<< "=== Arities ===" <<< nl # file = printlist (showpair showsymbol toString) "" m.arities file # file = file <<< "=== Type Rules ===" <<< nl # file = printlist (showpair showsymbol toString) "" m.typerules file # file = file <<< "=== Rules ===" <<< nl # file = printlist (showpair showsymbol (showlist showrule`)) "" m.rules file = file where showrule` rule = showruleanch showsymbol toString (map (const False) (arguments rule)) rule []