diff options
| author | krasimir <krasimir@chalmers.se> | 2009-12-13 18:50:29 +0000 |
|---|---|---|
| committer | krasimir <krasimir@chalmers.se> | 2009-12-13 18:50:29 +0000 |
| commit | f85232947e74ee7ef8c7b0ad2338212e7e68f1be (patch) | |
| tree | 667b886a5e3a4b026a63d4e3597f32497d824761 /src/runtime/haskell/PGF/Editor.hs | |
| parent | d88a865faff59c98fc91556ff8700b10ee5f2df8 (diff) | |
reorganize the directories under src, and rescue the JavaScript interpreter from deprecated
Diffstat (limited to 'src/runtime/haskell/PGF/Editor.hs')
| -rw-r--r-- | src/runtime/haskell/PGF/Editor.hs | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/src/runtime/haskell/PGF/Editor.hs b/src/runtime/haskell/PGF/Editor.hs new file mode 100644 index 000000000..3f69da170 --- /dev/null +++ b/src/runtime/haskell/PGF/Editor.hs @@ -0,0 +1,241 @@ +module PGF.Editor ( + State, -- datatype -- type-annotated possibly open tree with a focus + Dict, -- datatype -- abstract syntax information optimized for editing + Position, -- datatype -- path from top to focus + new, -- :: Type -> State -- create new State + refine, -- :: Dict -> CId -> State -> State -- refine focus with CId + replace, -- :: Dict -> Tree -> State -> State -- replace focus with Tree + delete, -- :: State -> State -- replace focus with ? + goNextMeta, -- :: State -> State -- move focus to next ? node + goNext, -- :: State -> State -- move to next node + goTop, -- :: State -> State -- move focus to the top (=root) + goPosition, -- :: Position -> State -> State -- move focus to given position + mkPosition, -- :: [Int] -> Position -- list of choices (top = []) + showPosition,-- :: Position -> [Int] -- readable position + focusType, -- :: State -> Type -- get the type of focus + stateTree, -- :: State -> Tree -- get the current tree + isMetaFocus, -- :: State -> Bool -- whether focus is ? + allMetas, -- :: State -> [(Position,Type)] -- all ?s and their positions + prState, -- :: State -> String -- print state, focus marked * + refineMenu, -- :: Dict -> State -> [CId] -- get refinement menu + pgf2dict -- :: PGF -> Dict -- create editing Dict from PGF + ) where + +import PGF.Data +import PGF.CId +import qualified Data.Map as M +import Debug.Trace ---- + +-- API + +new :: Type -> State +new (DTyp _ t _) = etree2state (uETree t) + +refine :: Dict -> CId -> State -> State +refine dict f = replaceInState (mkRefinement dict f) + +replace :: Dict -> Tree -> State -> State +replace dict t = replaceInState (tree2etree dict t) + +delete :: State -> State +delete s = replaceInState (uETree (typ (tree s))) s + +goNextMeta :: State -> State +goNextMeta s = + if isComplete s then s + else let s1 = goNext s in if isMetaFocus s1 + then s1 else goNextMeta s1 + +isComplete :: State -> Bool +isComplete s = isc (tree s) where + isc t = case atom t of + AMeta _ -> False + ACon _ -> all isc (children t) + +goTop :: State -> State +goTop = navigate (const top) + +goPosition :: [Int] -> State -> State +goPosition p s = s{position = p} + +mkPosition :: [Int] -> Position +mkPosition = id + +refineMenu :: Dict -> State -> [CId] +refineMenu dict s = maybe [] (map fst) $ M.lookup (focusBType s) (refines dict) + +focusType :: State -> Type +focusType s = btype2type (focusBType s) + +stateTree :: State -> Tree +stateTree = etree2tree . tree + +pgf2dict :: PGF -> Dict +pgf2dict pgf = Dict (M.fromAscList fus) refs where + fus = [(f,mkFType ty) | (f,(ty,_)) <- M.toList (funs abs)] + refs = M.fromAscList [(c, fusTo c) | (c,_) <- M.toList (cats abs)] + fusTo c = [(f,ty) | (f,ty@(_,k)) <- fus, k==c] ---- quadratic + mkFType (DTyp hyps c _) = ([k | Hyp _ (DTyp _ k _) <- hyps],c) ----dep types + abs = abstract pgf + +etree2tree :: ETree -> Tree +etree2tree t = case atom t of + ACon f -> Fun f (map etree2tree (children t)) + AMeta i -> Meta i + +tree2etree :: Dict -> Tree -> ETree +tree2etree dict t = case t of + Fun f _ -> annot (look f) t + where + annot (tys,ty) tr = case tr of + Fun f trs -> ETree (ACon f) ty [annt t tr | (t,tr) <- zip tys trs] + Meta i -> ETree (AMeta i) ty [] + annt ty tr = case tr of + Fun _ _ -> tree2etree dict tr + Meta _ -> annot ([],ty) tr + look f = maybe undefined id $ M.lookup f (functs dict) + +prState :: State -> String +prState s = unlines [replicate i ' ' ++ f | (i,f) <- pr [] (tree s)] where + pr i t = + (ind i,prAtom i (atom t)) : concat [pr (sub j i) c | (j,c) <- zip [0..] (children t)] + prAtom i a = prFocus i ++ case a of + ACon f -> prCId f + AMeta i -> "?" ++ show i + prFocus i = if i == position s then "*" else "" + ind i = 2 * length i + sub j i = i ++ [j] + +showPosition :: Position -> [Int] +showPosition = id + +allMetas :: State -> [(Position,Type)] +allMetas s = [(reverse p, btype2type ty) | (p,ty) <- metas [] (tree s)] where + metas p t = + (if isMetaAtom (atom t) then [(p,typ t)] else []) ++ + concat [metas (i:p) u | (i,u) <- zip [0..] (children t)] + +---- Trees and navigation + +data ETree = ETree { + atom :: Atom, + typ :: BType, + children :: [ETree] + } + deriving Show + +data Atom = + ACon CId + | AMeta Int + deriving Show + +btype2type :: BType -> Type +btype2type t = DTyp [] t [] + +uETree :: BType -> ETree +uETree ty = ETree (AMeta 0) ty [] + +data State = State { + position :: Position, + tree :: ETree + } + deriving Show + +type Position = [Int] + +top :: Position +top = [] + +up :: Position -> Position +up p = case p of + _:_ -> init p + _ -> p + +down :: Position -> Position +down = (++[0]) + +left :: Position -> Position +left p = case p of + _:_ | last p > 0 -> init p ++ [last p - 1] + _ -> top + +right :: Position -> Position +right p = case p of + _:_ -> init p ++ [last p + 1] + _ -> top + +etree2state :: ETree -> State +etree2state = State top + +doInState :: (ETree -> ETree) -> State -> State +doInState f s = s{tree = change (position s) (tree s)} where + change p t = case p of + [] -> f t + n:ns -> let (ts1,t0:ts2) = splitAt n (children t) in + t{children = ts1 ++ [change ns t0] ++ ts2} + +subtree :: Position -> ETree -> ETree +subtree p t = case p of + [] -> t + n:ns -> subtree ns (children t !! n) + +focus :: State -> ETree +focus s = subtree (position s) (tree s) + +focusBType :: State -> BType +focusBType s = typ (focus s) + +navigate :: (Position -> Position) -> State -> State +navigate p s = s{position = p (position s)} + +-- p is a fix-point aspect of state change +untilFix :: Eq a => (State -> a) -> (State -> Bool) -> (State -> State) -> State -> State +untilFix p b f s = + if b s + then s + else let fs = f s in if p fs == p s + then s + else untilFix p b f fs + +untilPosition :: (State -> Bool) -> (State -> State) -> State -> State +untilPosition = untilFix position + +goNext :: State -> State +goNext s = case focus s of + st | not (null (children st)) -> navigate down s + _ -> findSister s + where + findSister s = case s of + s' | null (position s') -> s' + s' | hasYoungerSisters s' -> navigate right s' + s' -> findSister (navigate up s') + hasYoungerSisters s = case position s of + p@(_:_) -> length (children (focus (navigate up s))) > last p + 1 + _ -> False + +isMetaFocus :: State -> Bool +isMetaFocus s = isMetaAtom (atom (focus s)) + +isMetaAtom :: Atom -> Bool +isMetaAtom a = case a of + AMeta _ -> True + _ -> False + +replaceInState :: ETree -> State -> State +replaceInState t = doInState (const t) + + +------- + +type BType = CId ----dep types +type FType = ([BType],BType) ----dep types + +data Dict = Dict { + functs :: M.Map CId FType, + refines :: M.Map BType [(CId,FType)] + } + +mkRefinement :: Dict -> CId -> ETree +mkRefinement dict f = ETree (ACon f) val (map uETree args) where + (args,val) = maybe undefined id $ M.lookup f (functs dict) + |
