1{-# LANGUAGE RecordWildCards #-}
2{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE NoMonomorphismRestriction #-}
4{-# LANGUAGE NamedFieldPuns #-}
5{- Evaluates the paramaterized terminfo string capability with the given parameters.
7 - todo: This can be greatly simplified.
9module Data.Terminfo.Eval ( cap_expression_required_bytes
10 , serialize_cap_expression
15import Data.Marshalling
16import Data.Terminfo.Parse
18import Control.Monad.Reader
19import Control.Monad.State.Strict
21import Data.Array.Unboxed
22import Data.Bits ( (.|.) )
26type Eval a = ReaderT (CapExpression,[CapParam]) (State [CapParam]) a
27type EvalIO a = ReaderT (CapExpression,[CapParam]) (StateT [CapParam] IO) a
29pop :: MonadState [CapParam] m => m CapParam
35read_param :: MonadReader (CapExpression, [CapParam]) m => Word -> m CapParam
38 return $ genericIndex params pn
40push :: MonadState [CapParam] m => CapParam -> m ()
45apply_param_ops :: CapExpression -> [CapParam] -> [CapParam]
46apply_param_ops cap params = foldl apply_param_op params (param_ops cap)
48apply_param_op :: [CapParam] -> ParamOp -> [CapParam]
49apply_param_op params IncFirstTwo = map (+ 1) params
51-- | range is 0-based offset into cap_bytes and count
53-- todo: The returned list is not assured to have a length st. length == count
54bytes_for_range :: CapExpression -> (Word8, Word8) -> [Word8]
55bytes_for_range cap (offset, count)
56 = take (fromEnum count)
57 $ drop (fromEnum offset)
61cap_expression_required_bytes :: CapExpression -> [CapParam] -> Word
62cap_expression_required_bytes cap params =
63 let params' = apply_param_ops cap params
64 in fst $ runState (runReaderT (cap_ops_required_bytes $ cap_ops cap) (cap, params)) []
66cap_ops_required_bytes :: CapOps -> Eval Word
67cap_ops_required_bytes ops = do
68 counts <- mapM cap_op_required_bytes ops
71cap_op_required_bytes :: CapOp -> Eval Word
72cap_op_required_bytes (Bytes (_, c)) = return $ toEnum $ fromEnum c
73cap_op_required_bytes DecOut = do
75 return $ toEnum $ length $ show p
76cap_op_required_bytes (PushParam pn) = do
77 read_param pn >>= push
79cap_op_required_bytes (Conditional expr parts) = do
80 c_expr <- cap_ops_required_bytes expr
81 c_parts <- foldM cond_parts_required_bytes 0 parts
82 return $ c_expr + c_parts
84 cond_parts_required_bytes in_c (true_ops, false_ops) = do
86 -- Usually the %? expr part pushes a value onto the stack, and %t pops it from the
87 -- stack, testing if it is nonzero (true). If it is zero (false), control
88 -- passes to the %e (else) part.
91 then cap_ops_required_bytes true_ops
92 else cap_ops_required_bytes false_ops
93 return $ in_c + c_branch
94cap_op_required_bytes BitwiseOr = do
99cap_op_required_bytes CompareEq = do
102 push $ if v_0 == v_1 then 1 else 0
104cap_op_required_bytes (LiteralInt i) = do
105 return $ toEnum $ length $ show i
107serialize_cap_expression :: CapExpression -> [CapParam] -> OutputBuffer -> IO OutputBuffer
108serialize_cap_expression cap params out_ptr = do
109 let params' = apply_param_ops cap params
110 (out_ptr', _) <- runStateT (runReaderT (serialize_cap_ops out_ptr (cap_ops cap)) (cap, params')) []
113serialize_cap_ops :: OutputBuffer -> CapOps -> EvalIO OutputBuffer
114serialize_cap_ops out_ptr ops = foldM serialize_cap_op out_ptr ops
116serialize_cap_op :: OutputBuffer -> CapOp -> EvalIO OutputBuffer
117serialize_cap_op out_ptr (Bytes (offset, c)) = do
119 let out_bytes = bytes_for_range cap (offset, c)
120 serialize_bytes out_bytes out_ptr
121serialize_cap_op out_ptr DecOut = do
124 out_bytes = string_to_bytes out_str
125 serialize_bytes out_bytes out_ptr
126serialize_cap_op out_ptr (PushParam pn) = do
127 read_param pn >>= push
129serialize_cap_op out_ptr (Conditional expr parts) = do
130 out_ptr' <- serialize_cap_ops out_ptr expr
131 out_ptr'' <- foldM serialize_cond_parts out_ptr' parts
134 serialize_cond_parts ptr (true_ops, false_ops) = do
136 -- Usually the %? expr part pushes a value onto the stack, and %t pops it from the
137 -- stack, testing if it is nonzero (true). If it is zero (false), control
138 -- passes to the %e (else) part.
141 then serialize_cap_ops ptr true_ops
142 else serialize_cap_ops ptr false_ops
144serialize_cap_op out_ptr BitwiseOr = do
149serialize_cap_op out_ptr CompareEq = do
152 push $ if v_0 == v_1 then 1 else 0
154serialize_cap_op out_ptr (LiteralInt i) = do
156 out_bytes = string_to_bytes out_str
157 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