diff options
| author | aarne <unknown> | 2004-11-08 09:22:37 +0000 |
|---|---|---|
| committer | aarne <unknown> | 2004-11-08 09:22:37 +0000 |
| commit | 7dd63a449f9683e56d310148cadd813599323a0b (patch) | |
| tree | 340bc2ebe4e9998269e06ac296ab3cbc02515e2c /examples/gfcc/compiler/Profile.hs | |
| parent | 2bd22e078aa0205f60bb414d2e7f17d73db1eaea (diff) | |
completing for release
Diffstat (limited to 'examples/gfcc/compiler/Profile.hs')
| -rw-r--r-- | examples/gfcc/compiler/Profile.hs | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/examples/gfcc/compiler/Profile.hs b/examples/gfcc/compiler/Profile.hs new file mode 100644 index 000000000..0c549cd67 --- /dev/null +++ b/examples/gfcc/compiler/Profile.hs @@ -0,0 +1,90 @@ +module Profile (postParse) where + +import Trees +import ErrM + +import Monad +import List (nub) + + +-- restoring parse trees for discontinuous constituents, bindings, etc. AR 25/1/2001 +-- revised 8/4/2002 for the new profile structure + +postParse :: CFTree -> Err Exp +postParse tree = do + iterm <- tree2term tree + return $ term2trm iterm + +-- an intermediate data structure +data ITerm = ITerm (Atom, BindVs) [ITerm] | IMeta deriving (Eq,Show) +type BindVs = [[Ident]] + +-- the job is done in two passes: +-- (1) tree2term: restore constituent order from Profile +-- (2) term2trm: restore Bindings from Binds + +tree2term :: CFTree -> Err ITerm +tree2term (CFTree (cff@(CFFun (fun,pro)), trees)) = case fun of + AM -> return IMeta + _ -> do + args <- mapM mkArg pro + binds <- mapM mkBinds pro + return $ ITerm (fun, binds) args + where + mkArg (_,arg) = case arg of + [x] -> do -- one occurrence + trx <- trees !? x + tree2term trx + [] -> return IMeta -- suppression + _ -> do -- reduplication + trees' <- mapM (trees !?) arg + xs1 <- mapM tree2term trees' + xs2 <- checkArity xs1 + unif xs2 + + checkArity xs = if length (nub [length xx | ITerm _ xx <- xs']) > 1 + then Bad "arity error" + else return xs' + where xs' = [t | t@(ITerm _ _) <- xs] + unif xs = case [t | t@(ITerm _ _) <- xs] of + [] -> return $ IMeta + (ITerm fp@(f,_) xx : ts) -> do + let hs = [h | ITerm (h,_) _ <- ts, h /= f] + testErr (null hs) -- if fails, hs must be nonempty + ("unification expects " ++ prt f ++ " but found " ++ prt (head hs)) + xx' <- mapM unifArg [0 .. length xx - 1] + return $ ITerm fp xx' + where + unifArg i = unif [zz !! i | ITerm _ zz <- xs] + + mkBinds (xss,_) = mapM mkBind xss + mkBind xs = do + ts <- mapM (trees !?) xs + let vs = [x | CFTree (CFFun (AV x,_),[]) <- ts] + testErr (length ts == length vs) "non-variable in bound position" + case vs of + [x] -> return x + [] -> return $ Ident "h_" ---- uBoundVar + y:ys -> do + testErr (all (==y) ys) ("fail to unify bindings of " ++ prt y) + return y + +term2trm :: ITerm -> Exp +term2trm IMeta = EAtom AM +term2trm (ITerm (fun, binds) terms) = + let bterms = zip binds terms + in mkAppAtom fun [mkAbsR xs (term2trm t) | (xs,t) <- bterms] + + --- these are deprecated + where + mkAbsR c e = foldr EAbs e c + mkAppAtom a = mkApp (EAtom a) + mkApp = foldl EApp + +-- !! with the error monad +(!?) :: [a] -> Int -> Err a +xs !? i = foldr (const . return) (Bad "too few elements in list") $ drop i xs + +testErr :: Bool -> String -> Err () +testErr cond msg = if cond then return () else Bad msg + |
