{-# LANGUAGE OverloadedStrings #-}
-- | Evaluates CSS media queries for @import & @media.
-- INTERNAL MODULE
module Data.CSS.Preprocessor.Conditions.Expr(
        Expr, Op(..), parse, parse', eval, Datum(..)
    ) where

import Data.CSS.Syntax.Tokens(Token(..))
import Data.Text.Internal (Text(..))
import Data.Text (stripPrefix)

-- | A parsed (post-order) expression.
type Expr = [Op]
-- | Operators understood by media queries.
data Op = And -- ^ Is true if both operands are true
    | Or -- ^ Is true if either operand is true
    | Not -- ^ Is true if it's operand isn't.
    | Var Text -- ^ Queries the value of an externally-specified parameter.
    | Tok Token -- ^ Tokens to be evaluated as specified by caller.
    | MkRatio -- ^ Pushes a ratio value to stack, for querying screensize.
    | Less -- ^ Is the left operand smaller than right?
    | LessEq -- ^ Is the left operand smaller or the same as right?
    | Equal -- ^ Are the operands the same?
    | Greater -- ^ Is the left operand bigger than right?
    | GreaterEq -- ^ Is the left operand bigger or the same as right?
    deriving (Int -> Op -> ShowS
[Op] -> ShowS
Op -> String
(Int -> Op -> ShowS)
-> (Op -> String) -> ([Op] -> ShowS) -> Show Op
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Op] -> ShowS
$cshowList :: [Op] -> ShowS
show :: Op -> String
$cshow :: Op -> String
showsPrec :: Int -> Op -> ShowS
$cshowsPrec :: Int -> Op -> ShowS
Show, Op -> Op -> Bool
(Op -> Op -> Bool) -> (Op -> Op -> Bool) -> Eq Op
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Op -> Op -> Bool
$c/= :: Op -> Op -> Bool
== :: Op -> Op -> Bool
$c== :: Op -> Op -> Bool
Eq)

-- | Parses a media query to postorder form, returning the tokens after the given delimiter.
parse :: Token -> [Token] -> (Expr, [Token])
parse :: Token -> [Token] -> ([Op], [Token])
parse end :: Token
end toks :: [Token]
toks = let (toks' :: [Token]
toks', rest :: [Token]
rest) = (Token -> Bool) -> [Token] -> ([Token], [Token])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (Token -> Token -> Bool
forall a. Eq a => a -> a -> Bool
== Token
end) [Token]
toks in ([Token] -> [(Op, Int)] -> [Op]
parse' [Token]
toks' [], [Token]
rest)

--------
---- Shunting Yard parser
--------
-- | Parses a media query to postorder form, given an operator stack.
parse' :: [Token] -> [(Op, Int)] -> Expr
parse' :: [Token] -> [(Op, Int)] -> [Op]
parse' (Whitespace:toks :: [Token]
toks) ops :: [(Op, Int)]
ops = [Token] -> [(Op, Int)] -> [Op]
parse' [Token]
toks [(Op, Int)]
ops

parse' (Comma:toks :: [Token]
toks) ops :: [(Op, Int)]
ops = [Token] -> Op -> Int -> [(Op, Int)] -> [Op]
pushOp [Token]
toks Op
Or 10 [(Op, Int)]
ops
parse' (Ident "not":toks :: [Token]
toks) ops :: [(Op, Int)]
ops = [Token] -> Op -> Int -> [(Op, Int)] -> [Op]
pushOp [Token]
toks Op
Not 20 [(Op, Int)]
ops
parse' (Function "not":toks :: [Token]
toks) ops :: [(Op, Int)]
ops = [Token] -> Op -> Int -> [(Op, Int)] -> [Op]
pushOp [Token]
toks Op
Not 0 [(Op, Int)]
ops
parse' (Ident "only":toks :: [Token]
toks) ops :: [(Op, Int)]
ops = [Token] -> [(Op, Int)] -> [Op]
parse' [Token]
toks [(Op, Int)]
ops
parse' (Ident "and":toks :: [Token]
toks) ops :: [(Op, Int)]
ops = [Token] -> Op -> Int -> [(Op, Int)] -> [Op]
pushOp [Token]
toks Op
And 30 [(Op, Int)]
ops
parse' (Ident "or":toks :: [Token]
toks) ops :: [(Op, Int)]
ops = [Token] -> Op -> Int -> [(Op, Int)] -> [Op]
pushOp [Token]
toks Op
Or 30 [(Op, Int)]
ops
parse' (Delim '<':Delim '=':toks :: [Token]
toks) ops :: [(Op, Int)]
ops = [Token] -> Op -> Int -> [(Op, Int)] -> [Op]
pushOp [Token]
toks Op
LessEq 40 [(Op, Int)]
ops
parse' (Delim '<':toks :: [Token]
toks) ops :: [(Op, Int)]
ops = [Token] -> Op -> Int -> [(Op, Int)] -> [Op]
pushOp [Token]
toks Op
Less 40 [(Op, Int)]
ops
parse' (Delim '>':Delim '=':toks :: [Token]
toks) ops :: [(Op, Int)]
ops = [Token] -> Op -> Int -> [(Op, Int)] -> [Op]
pushOp [Token]
toks Op
GreaterEq 40 [(Op, Int)]
ops
parse' (Delim '>':toks :: [Token]
toks) ops :: [(Op, Int)]
ops = [Token] -> Op -> Int -> [(Op, Int)] -> [Op]
pushOp [Token]
toks Op
Greater 40 [(Op, Int)]
ops
parse' (Colon:tok :: Token
tok:toks :: [Token]
toks) ops :: [(Op, Int)]
ops = Token -> Op
Tok Token
tok Op -> [Op] -> [Op]
forall a. a -> [a] -> [a]
: [Token] -> Op -> Int -> [(Op, Int)] -> [Op]
pushOp [Token]
toks Op
Equal 40 [(Op, Int)]
ops
parse' (Delim '/':toks :: [Token]
toks) ops :: [(Op, Int)]
ops = [Token] -> Op -> Int -> [(Op, Int)] -> [Op]
pushOp [Token]
toks Op
MkRatio 50 [(Op, Int)]
ops

parse' (LeftParen:toks :: [Token]
toks) ops :: [(Op, Int)]
ops = [Token] -> Op -> Int -> [(Op, Int)] -> [Op]
pushOp [Token]
toks (Text -> Op
Var ")") 0 [(Op, Int)]
ops
parse' (RightParen:toks :: [Token]
toks) ((Var ")", 0):ops :: [(Op, Int)]
ops) = [Token] -> [(Op, Int)] -> [Op]
parse' [Token]
toks [(Op, Int)]
ops
parse' (RightParen:toks :: [Token]
toks) ((Not, 0):ops :: [(Op, Int)]
ops) = Op
Not Op -> [Op] -> [Op]
forall a. a -> [a] -> [a]
: [Token] -> [(Op, Int)] -> [Op]
parse' [Token]
toks [(Op, Int)]
ops -- Functional not syntax
parse' toks :: [Token]
toks@(RightParen:_) ((op :: Op
op, _):ops :: [(Op, Int)]
ops) = Op
op Op -> [Op] -> [Op]
forall a. a -> [a] -> [a]
: [Token] -> [(Op, Int)] -> [Op]
parse' [Token]
toks [(Op, Int)]
ops
parse' (RightParen:_) [] = [] -- Invalid!
parse' (Ident var :: Text
var:toks :: [Token]
toks) ops :: [(Op, Int)]
ops@((peek :: Op
peek, _):ops' :: [(Op, Int)]
ops')
    -- First, fix up various range syntaxes.
    | Op
peek Op -> [Op] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Op
Less, Op
LessEq, Op
Greater, Op
GreaterEq] = -- Chained conditions
        Text -> Op
Var Text
var Op -> [Op] -> [Op]
forall a. a -> [a] -> [a]
: Op
peek Op -> [Op] -> [Op]
forall a. a -> [a] -> [a]
: Text -> Op
Var Text
var Op -> [Op] -> [Op]
forall a. a -> [a] -> [a]
: [Token] -> [(Op, Int)] -> [Op]
parse' [Token]
toks [(Op, Int)]
ops'
    | Just var' :: Text
var' <- Text -> Text -> Maybe Text
stripPrefix "max-" Text
var = Text -> Op
Var Text
var' Op -> [Op] -> [Op]
forall a. a -> [a] -> [a]
: [Token] -> Op -> Int -> [(Op, Int)] -> [Op]
pushOp [Token]
toks Op
LessEq 1000 [(Op, Int)]
ops
    | Just var' :: Text
var' <- Text -> Text -> Maybe Text
stripPrefix "min-" Text
var = Text -> Op
Var Text
var' Op -> [Op] -> [Op]
forall a. a -> [a] -> [a]
: [Token] -> Op -> Int -> [(Op, Int)] -> [Op]
pushOp [Token]
toks Op
GreaterEq 1000 [(Op, Int)]
ops
    | Bool
otherwise = Text -> Op
Var Text
var Op -> [Op] -> [Op]
forall a. a -> [a] -> [a]
: [Token] -> [(Op, Int)] -> [Op]
parse' [Token]
toks [(Op, Int)]
ops
parse' (tok :: Token
tok:toks :: [Token]
toks) ops :: [(Op, Int)]
ops = Token -> Op
Tok Token
tok Op -> [Op] -> [Op]
forall a. a -> [a] -> [a]
: [Token] -> [(Op, Int)] -> [Op]
parse' [Token]
toks [(Op, Int)]
ops
parse' [] ops :: [(Op, Int)]
ops = [Op
op | (op :: Op
op, _) <- [(Op, Int)]
ops]

pushOp :: [Token] -> Op -> Int -> [(Op, Int)] -> Expr
pushOp :: [Token] -> Op -> Int -> [(Op, Int)] -> [Op]
pushOp toks :: [Token]
toks op :: Op
op b :: Int
b ((peek :: Op
peek, b' :: Int
b'):ops' :: [(Op, Int)]
ops') | Int
b' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
b = Op
peek Op -> [Op] -> [Op]
forall a. a -> [a] -> [a]
: [Token] -> Op -> Int -> [(Op, Int)] -> [Op]
pushOp [Token]
toks Op
op Int
b [(Op, Int)]
ops'
pushOp toks :: [Token]
toks op :: Op
op b :: Int
b ops :: [(Op, Int)]
ops = [Token] -> [(Op, Int)] -> [Op]
parse' [Token]
toks ((Op
op, Int
b)(Op, Int) -> [(Op, Int)] -> [(Op, Int)]
forall a. a -> [a] -> [a]
:[(Op, Int)]
ops)

--------
---- Shunting Yard Evaluator
--------
-- | Dynamic types for evaluating media queries.
data Datum = B Bool | N Float | R {Datum -> Float
minv :: Float, Datum -> Float
maxv :: Float} deriving Datum -> Datum -> Bool
(Datum -> Datum -> Bool) -> (Datum -> Datum -> Bool) -> Eq Datum
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Datum -> Datum -> Bool
$c/= :: Datum -> Datum -> Bool
== :: Datum -> Datum -> Bool
$c== :: Datum -> Datum -> Bool
Eq

-- | Evaluates a media query with the given functions for evaluating vars & tokens.
eval :: (Text -> Datum) -> (Token -> Datum) -> Expr -> Bool
eval :: (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' []

eval' :: [Datum] -> (Text -> Datum) -> (Token -> Datum) -> Expr -> Bool
eval' :: [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (B y :: Bool
y:B x :: Bool
x:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (And:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Bool
x Bool -> Bool -> Bool
&& Bool
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (B y :: Bool
y:B x :: Bool
x:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (Or:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Bool
x Bool -> Bool -> Bool
|| Bool
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (B x :: Bool
x:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (Not:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Bool -> Bool
not Bool
x)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' stack :: [Datum]
stack v :: Text -> Datum
v t :: Token -> Datum
t (Var name :: Text
name:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Text -> Datum
v Text
nameDatum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
-- Have tokens lower to variables, to make things easier for the callee.
eval' stack :: [Datum]
stack v :: Text -> Datum
v t :: Token -> Datum
t (Tok tok :: Token
tok:ops :: [Op]
ops) | Token -> Datum
t Token
tok Datum -> Datum -> Bool
forall a. Eq a => a -> a -> Bool
/= Bool -> Datum
B Bool
False = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Token -> Datum
t Token
tokDatum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' stack :: [Datum]
stack v :: Text -> Datum
v t :: Token -> Datum
t (Tok (Ident name :: Text
name):ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Text -> Datum
v Text
nameDatum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
-- Ratios should be compared as floating point...
eval' (N y :: Float
y:N x :: Float
x:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (MkRatio:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Float -> Datum
N (Float
x Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (N y :: Float
y:N x :: Float
x:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (Less:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Float
x Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (R _ y :: Float
y:N x :: Float
x:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (Less:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Float
x Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (N y :: Float
y: R x :: Float
x _:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (Less:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Float
x Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (R _ y :: Float
y:R x :: Float
x _:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (Less:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Float
x Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (N y :: Float
y:N x :: Float
x:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (LessEq:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Float
x Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
<= Float
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (R _ y :: Float
y:N x :: Float
x:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (LessEq:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Float
x Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
<= Float
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (N y :: Float
y: R x :: Float
x _:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (LessEq:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Float
x Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
<= Float
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (R _ y :: Float
y:R x :: Float
x _:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (LessEq:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Float
x Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
<= Float
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (R yMin :: Float
yMin yMax :: Float
yMax:R xMin :: Float
xMin xMax :: Float
xMax:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (Equal:ops :: [Op]
ops) =
    [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Float
xMax Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
>= Float
yMin Bool -> Bool -> Bool
&& Float
xMin Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
<= Float
yMax) Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
: [Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (N y :: Float
y: N x :: Float
x:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (Equal:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Float
x Float -> Float -> Bool
forall a. Eq a => a -> a -> Bool
== Float
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (N y :: Float
y:N x :: Float
x:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (Greater:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Float
x Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (R y :: Float
y _:N x :: Float
x:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (Greater:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Float
x Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (N y :: Float
y:R _ x :: Float
x:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (Greater:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Float
x Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (R y :: Float
y _:R _ x :: Float
x:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (Greater:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Float
x Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (N y :: Float
y:N x :: Float
x:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (GreaterEq:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Float
x Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
>= Float
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (R y :: Float
y _:N x :: Float
x:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (GreaterEq:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Float
x Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
>= Float
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (N y :: Float
y:R _ x :: Float
x:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (GreaterEq:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Float
x Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
>= Float
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (R y :: Float
y _:R _ x :: Float
x:stack :: [Datum]
stack) v :: Text -> Datum
v t :: Token -> Datum
t (GreaterEq:ops :: [Op]
ops) = [Datum] -> (Text -> Datum) -> (Token -> Datum) -> [Op] -> Bool
eval' (Bool -> Datum
B (Float
x Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
>= Float
y)Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
:[Datum]
stack) Text -> Datum
v Token -> Datum
t [Op]
ops
eval' (B ret :: Bool
ret:_) _ _ [] = Bool
ret
eval' [] _ _ [] = Bool
True -- Special case
eval' _ _ _ _ = Bool
False -- Error handling fallback.