1{-# LANGUAGE RecordWildCards #-}
2{-# LANGUAGE TypeFamilies #-}
3{-# LANGUAGE FlexibleContexts #-}
4{-# LANGUAGE NoMonomorphismRestriction #-}
5{-# LANGUAGE NamedFieldPuns #-}
6{- Evaluates the paramaterized terminfo string capability with the given parameters.
8 - todo: This can be greatly simplified.
10module Data.Terminfo.Eval ( cap_expression_required_bytes
11 , serialize_cap_expression
16import Data.Marshalling
17import Data.Terminfo.Parse
19import Control.Monad.Reader
20import Control.Monad.State.Strict
22import Data.Array.Unboxed
23import Data.Bits ( (.|.) )
27type Eval a = ReaderT (CapExpression,[CapParam]) (State [CapParam]) a
28type EvalIO a = ReaderT (CapExpression,[CapParam]) (StateT [CapParam] IO) a
30pop :: (StateType m ~ [CapParam], MonadState m) => m CapParam
36read_param :: (EnvType m ~ (CapExpression, [CapParam]), MonadReader m) => Word -> m CapParam
39 return $ genericIndex params pn
41push :: (StateType m ~ [CapParam], MonadState m) => CapParam -> m ()
46apply_param_ops :: CapExpression -> [CapParam] -> [CapParam]
47apply_param_ops cap params = foldl apply_param_op params (param_ops cap)
49apply_param_op :: [CapParam] -> ParamOp -> [CapParam]
50apply_param_op params IncFirstTwo = map (+ 1) params
52-- | range is 0-based offset into cap_bytes and count
54-- todo: The returned list is not assured to have a length st. length == count
55bytes_for_range :: CapExpression -> (Word8, Word8) -> [Word8]
56bytes_for_range cap (offset, count)
57 = take (fromEnum count)
58 $ drop (fromEnum offset)
62cap_expression_required_bytes :: CapExpression -> [CapParam] -> Word
63cap_expression_required_bytes cap params =
64 let params' = apply_param_ops cap params
65 in fst $ runState (runReaderT (cap_ops_required_bytes $ cap_ops cap) (cap, params)) []
67cap_ops_required_bytes :: CapOps -> Eval Word
68cap_ops_required_bytes ops = do
69 counts <- mapM cap_op_required_bytes ops
72cap_op_required_bytes :: CapOp -> Eval Word
73cap_op_required_bytes (Bytes (_, c)) = return $ toEnum $ fromEnum c
74cap_op_required_bytes DecOut = do
76 return $ toEnum $ length $ show p
77cap_op_required_bytes (PushParam pn) = do
78 read_param pn >>= push
80cap_op_required_bytes (Conditional expr parts) = do
81 c_expr <- cap_ops_required_bytes expr
82 c_parts <- foldM cond_parts_required_bytes 0 parts
83 return $ c_expr + c_parts
85 cond_parts_required_bytes in_c (true_ops, false_ops) = do
87 -- Usually the %? expr part pushes a value onto the stack, and %t pops it from the
88 -- stack, testing if it is nonzero (true). If it is zero (false), control
89 -- passes to the %e (else) part.
92 then cap_ops_required_bytes true_ops
93 else cap_ops_required_bytes false_ops
94 return $ in_c + c_branch
95cap_op_required_bytes BitwiseOr = do
100cap_op_required_bytes CompareEq = do
103 push $ if v_0 == v_1 then 1 else 0
105cap_op_required_bytes (LiteralInt i) = do
106 return $ toEnum $ length $ show i
108serialize_cap_expression :: CapExpression -> [CapParam] -> OutputBuffer -> IO OutputBuffer
109serialize_cap_expression cap params out_ptr = do
110 let params' = apply_param_ops cap params
111 (out_ptr', _) <- runStateT (runReaderT (serialize_cap_ops out_ptr (cap_ops cap)) (cap, params')) []
114serialize_cap_ops :: OutputBuffer -> CapOps -> EvalIO OutputBuffer
115serialize_cap_ops out_ptr ops = foldM serialize_cap_op out_ptr ops
117serialize_cap_op :: OutputBuffer -> CapOp -> EvalIO OutputBuffer
118serialize_cap_op out_ptr (Bytes (offset, c)) = do
120 let out_bytes = bytes_for_range cap (offset, c)
121 serialize_bytes out_bytes out_ptr
122serialize_cap_op out_ptr DecOut = do
125 out_bytes = string_to_bytes out_str
126 serialize_bytes out_bytes out_ptr
127serialize_cap_op out_ptr (PushParam pn) = do
128 read_param pn >>= push
130serialize_cap_op out_ptr (Conditional expr parts) = do
131 out_ptr' <- serialize_cap_ops out_ptr expr
132 out_ptr'' <- foldM serialize_cond_parts out_ptr' parts
135 serialize_cond_parts ptr (true_ops, false_ops) = do
137 -- Usually the %? expr part pushes a value onto the stack, and %t pops it from the
138 -- stack, testing if it is nonzero (true). If it is zero (false), control
139 -- passes to the %e (else) part.
142 then serialize_cap_ops ptr true_ops
143 else serialize_cap_ops ptr false_ops
145serialize_cap_op out_ptr BitwiseOr = do
150serialize_cap_op out_ptr CompareEq = do
153 push $ if v_0 == v_1 then 1 else 0
155serialize_cap_op out_ptr (LiteralInt i) = do
157 out_bytes = string_to_bytes out_str
158 serialize_bytes out_bytes out_ptr
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list