fay 0.12.0.1 → 0.14.0.0
raw patch · 75 files changed
+4035/−6660 lines, 75 filesdep +Cabaldep −groomdep −randomdep ~blaze-htmlPVP ok
version bump matches the API change (PVP)
Dependencies added: Cabal
Dependencies removed: groom, random
Dependency ranges changed: blaze-html
API changes (from Hackage documentation)
- Language.Fay: compileFile :: CompileConfig -> FilePath -> IO (Either CompileError String)
- Language.Fay: compileFileWithState :: CompileConfig -> FilePath -> IO (Either CompileError (String, CompileState))
- Language.Fay: compileFromTo :: CompileConfig -> FilePath -> Maybe FilePath -> IO ()
- Language.Fay: compileFromToAndGenerateHtml :: CompileConfig -> FilePath -> FilePath -> IO (Either CompileError String)
- Language.Fay: showCompileError :: CompileError -> String
- Language.Fay: toJsName :: String -> String
- Language.Fay.Compiler: compileDecl :: Bool -> Decl -> Compile [JsStmt]
- Language.Fay.Compiler: compileExp :: Exp -> Compile JsExp
- Language.Fay.Compiler: compileForDocs :: Module -> Compile [JsStmt]
- Language.Fay.Compiler: compileModule :: Module -> Compile [JsStmt]
- Language.Fay.Compiler: compileToAst :: (Show from, Show to, CompilesTo from to) => FilePath -> CompileReader -> CompileState -> (from -> Compile to) -> String -> IO (Either CompileError (to, CompileState))
- Language.Fay.Compiler: compileToplevelModule :: Module -> Compile [JsStmt]
- Language.Fay.Compiler: compileViaStr :: (Show from, Show to, CompilesTo from to) => FilePath -> CompileConfig -> (from -> Compile to) -> String -> IO (Either CompileError (PrintState, CompileState))
- Language.Fay.Compiler: instance CompilesTo Decl [JsStmt]
- Language.Fay.Compiler: instance CompilesTo Exp JsExp
- Language.Fay.Compiler: instance CompilesTo Module [JsStmt]
- Language.Fay.Compiler: printCompile :: (Show from, Show to, CompilesTo from to) => CompileConfig -> (from -> Compile to) -> String -> IO ()
- Language.Fay.Compiler: printTestCompile :: String -> IO ()
- Language.Fay.Compiler: runCompile :: CompileReader -> CompileState -> Compile a -> IO (Either CompileError (a, CompileState))
- Language.Fay.Compiler.FFI: compileFFI :: SrcLoc -> Name -> String -> Type -> Compile [JsStmt]
- Language.Fay.Compiler.FFI: emitFayToJs :: Name -> [([Name], BangType)] -> Compile ()
- Language.Fay.Compiler.FFI: emitJsToFay :: Name -> [([Name], BangType)] -> Compile ()
- Language.Fay.Compiler.FFI: fayToJsDispatcher :: [JsStmt] -> JsStmt
- Language.Fay.Compiler.FFI: jsToFayDispatcher :: [JsStmt] -> JsStmt
- Language.Fay.Compiler.Misc: anyM :: Monad m => (a -> m Bool) -> [a] -> m Bool
- Language.Fay.Compiler.Misc: bindToplevel :: SrcLoc -> Bool -> Name -> JsExp -> Compile JsStmt
- Language.Fay.Compiler.Misc: bindVar :: Name -> Compile ()
- Language.Fay.Compiler.Misc: config :: (CompileConfig -> a) -> Compile a
- Language.Fay.Compiler.Misc: emitExport :: ExportSpec -> Compile ()
- Language.Fay.Compiler.Misc: fayBuiltin :: String -> QName
- Language.Fay.Compiler.Misc: force :: JsExp -> JsExp
- Language.Fay.Compiler.Misc: generateScope :: Compile a -> Compile ()
- Language.Fay.Compiler.Misc: getGhcPackageDbFlag :: IO String
- Language.Fay.Compiler.Misc: isConstant :: JsExp -> Bool
- Language.Fay.Compiler.Misc: isWildCardAlt :: Alt -> Bool
- Language.Fay.Compiler.Misc: isWildCardPat :: Pat -> Bool
- Language.Fay.Compiler.Misc: optimizePatConditions :: [[JsStmt]] -> [[JsStmt]]
- Language.Fay.Compiler.Misc: parseResult :: ((SrcLoc, String) -> b) -> (a -> b) -> ParseResult a -> b
- Language.Fay.Compiler.Misc: printSrcLoc :: SrcLoc -> String
- Language.Fay.Compiler.Misc: qualify :: Name -> Compile QName
- Language.Fay.Compiler.Misc: resolveName :: QName -> Compile QName
- Language.Fay.Compiler.Misc: stmtsThunk :: [JsStmt] -> JsExp
- Language.Fay.Compiler.Misc: throw :: String -> JsExp -> JsStmt
- Language.Fay.Compiler.Misc: throwExp :: String -> JsExp -> JsExp
- Language.Fay.Compiler.Misc: thunk :: JsExp -> JsExp
- Language.Fay.Compiler.Misc: typeToFields :: QName -> Compile [QName]
- Language.Fay.Compiler.Misc: typeToRecs :: QName -> Compile [QName]
- Language.Fay.Compiler.Misc: uniqueNames :: [JsName]
- Language.Fay.Compiler.Misc: unname :: Name -> String
- Language.Fay.Compiler.Misc: warn :: String -> Compile ()
- Language.Fay.Compiler.Misc: withModuleScope :: Compile a -> Compile a
- Language.Fay.Compiler.Misc: withScope :: Compile a -> Compile a
- Language.Fay.Compiler.Misc: withScopedTmpJsName :: (JsName -> Compile a) -> Compile a
- Language.Fay.Compiler.Misc: withScopedTmpName :: (Name -> Compile a) -> Compile a
- Language.Fay.Compiler.Optimizer: OptState :: [JsStmt] -> [QName] -> OptState
- Language.Fay.Compiler.Optimizer: applyToExpsInStmt :: [FuncArity] -> ([FuncArity] -> JsExp -> Optimize JsExp) -> JsStmt -> Optimize JsStmt
- Language.Fay.Compiler.Optimizer: applyToExpsInStmts :: ([FuncArity] -> JsExp -> Optimize JsExp) -> [JsStmt] -> Optimize [JsStmt]
- Language.Fay.Compiler.Optimizer: collectFuncs :: [JsStmt] -> [FuncArity]
- Language.Fay.Compiler.Optimizer: data OptState
- Language.Fay.Compiler.Optimizer: expArity :: JsExp -> Int
- Language.Fay.Compiler.Optimizer: optStmts :: OptState -> [JsStmt]
- Language.Fay.Compiler.Optimizer: optUncurry :: OptState -> [QName]
- Language.Fay.Compiler.Optimizer: optimizeToplevel :: [JsStmt] -> Optimize [JsStmt]
- Language.Fay.Compiler.Optimizer: renameUncurried :: QName -> QName
- Language.Fay.Compiler.Optimizer: runOptimizer :: ([JsStmt] -> Optimize [JsStmt]) -> [JsStmt] -> [JsStmt]
- Language.Fay.Compiler.Optimizer: stripAndUncurry :: [JsStmt] -> Optimize [JsStmt]
- Language.Fay.Compiler.Optimizer: tco :: [JsStmt] -> [JsStmt]
- Language.Fay.Compiler.Optimizer: test :: IO ()
- Language.Fay.Compiler.Optimizer: type FuncArity = (QName, Int)
- Language.Fay.Compiler.Optimizer: type Optimize = State OptState
- Language.Fay.Compiler.Optimizer: uncurryBinding :: [JsStmt] -> QName -> Maybe JsStmt
- Language.Fay.Compiler.Optimizer: walkAndStripForces :: [FuncArity] -> JsExp -> Optimize (Maybe JsExp)
- Language.Fay.Compiler.Packages: checkDirExists :: FilePath -> IO ()
- Language.Fay.Compiler.Packages: describePackage :: Maybe FilePath -> String -> IO String
- Language.Fay.Compiler.Packages: resolvePackage :: CompileConfig -> String -> IO CompileConfig
- Language.Fay.Compiler.Packages: resolvePackages :: CompileConfig -> IO CompileConfig
- Language.Fay.Compiler.Packages: shareDirs :: String -> Maybe [FilePath]
- Language.Fay.Convert: readFromFay :: Data a => Value -> Maybe a
- Language.Fay.Convert: showToFay :: Show a => a -> Maybe Value
- Language.Fay.FFI: class Foreign a
- Language.Fay.FFI: instance (Foreign a, Foreign b) => Foreign (a -> b)
- Language.Fay.FFI: instance (Foreign a, Foreign b) => Foreign (a, b)
- Language.Fay.FFI: instance (Foreign a, Foreign b, Foreign c) => Foreign (a, b, c)
- Language.Fay.FFI: instance (Foreign a, Foreign b, Foreign c, Foreign d) => Foreign (a, b, c, d)
- Language.Fay.FFI: instance (Foreign a, Foreign b, Foreign c, Foreign d, Foreign e) => Foreign (a, b, c, d, e)
- Language.Fay.FFI: instance (Foreign a, Foreign b, Foreign c, Foreign d, Foreign e, Foreign f) => Foreign (a, b, c, d, e, f)
- Language.Fay.FFI: instance (Foreign a, Foreign b, Foreign c, Foreign d, Foreign e, Foreign f, Foreign g) => Foreign (a, b, c, d, e, f, g)
- Language.Fay.FFI: instance Foreign ()
- Language.Fay.FFI: instance Foreign Bool
- Language.Fay.FFI: instance Foreign Char
- Language.Fay.FFI: instance Foreign Double
- Language.Fay.FFI: instance Foreign Int
- Language.Fay.FFI: instance Foreign a => Foreign (Defined a)
- Language.Fay.FFI: instance Foreign a => Foreign (Fay a)
- Language.Fay.FFI: instance Foreign a => Foreign (Maybe a)
- Language.Fay.FFI: instance Foreign a => Foreign (Nullable a)
- Language.Fay.FFI: instance Foreign a => Foreign [a]
- Language.Fay.ModuleScope: bindAsLocals :: [QName] -> ModuleScope -> ModuleScope
- Language.Fay.ModuleScope: data ModuleScope
- Language.Fay.ModuleScope: findTopLevelNames :: ModuleName -> [Decl] -> ModuleScope
- Language.Fay.ModuleScope: instance Default ModuleScope
- Language.Fay.ModuleScope: instance Monoid ModuleScope
- Language.Fay.ModuleScope: instance Show ModuleScope
- Language.Fay.ModuleScope: moduleLocals :: ModuleName -> ModuleScope -> [QName]
- Language.Fay.ModuleScope: resolveName :: QName -> ModuleScope -> Maybe QName
- Language.Fay.Prelude: (!!) :: [a] -> Int -> a
- Language.Fay.Prelude: ($!) :: (a -> b) -> a -> b
- Language.Fay.Prelude: ($) :: (t1 -> t) -> t1 -> t
- Language.Fay.Prelude: (&&) :: Bool -> Bool -> Bool
- Language.Fay.Prelude: (*) :: Num a => a -> a -> a
- Language.Fay.Prelude: (**) :: Double -> Double -> Double
- Language.Fay.Prelude: (+) :: Num a => a -> a -> a
- Language.Fay.Prelude: (++) :: [a] -> [a] -> [a]
- Language.Fay.Prelude: (-) :: Num a => a -> a -> a
- Language.Fay.Prelude: (.) :: (t1 -> t) -> (t2 -> t1) -> t2 -> t
- Language.Fay.Prelude: (/) :: Fractional a => a -> a -> a
- Language.Fay.Prelude: (/=) :: Eq a => a -> a -> Bool
- Language.Fay.Prelude: (<) :: Ord a => a -> a -> Bool
- Language.Fay.Prelude: (<=) :: Ord a => a -> a -> Bool
- Language.Fay.Prelude: (=<<) :: Monad m => (a -> m b) -> m a -> m b
- Language.Fay.Prelude: (==) :: Eq a => a -> a -> Bool
- Language.Fay.Prelude: (>) :: Ord a => a -> a -> Bool
- Language.Fay.Prelude: (>=) :: Ord a => a -> a -> Bool
- Language.Fay.Prelude: (>>) :: Fay a -> Fay b -> Fay b
- Language.Fay.Prelude: (>>=) :: Fay a -> (a -> Fay b) -> Fay b
- Language.Fay.Prelude: (^) :: Num a => a -> Int -> a
- Language.Fay.Prelude: (^^) :: Double -> Int -> Double
- Language.Fay.Prelude: (||) :: Bool -> Bool -> Bool
- Language.Fay.Prelude: EQ :: Ordering
- Language.Fay.Prelude: False :: Bool
- Language.Fay.Prelude: GT :: Ordering
- Language.Fay.Prelude: Just :: a -> Maybe a
- Language.Fay.Prelude: LT :: Ordering
- Language.Fay.Prelude: Left :: a -> Either a b
- Language.Fay.Prelude: Nothing :: Maybe a
- Language.Fay.Prelude: Right :: b -> Either a b
- Language.Fay.Prelude: True :: Bool
- Language.Fay.Prelude: abs :: (Num a, Ord a) => a -> a
- Language.Fay.Prelude: acos :: Double -> Double
- Language.Fay.Prelude: acosh :: Double -> Double
- Language.Fay.Prelude: all :: (a -> Bool) -> [a] -> Bool
- Language.Fay.Prelude: and :: [Bool] -> Bool
- Language.Fay.Prelude: any :: (a -> Bool) -> [a] -> Bool
- Language.Fay.Prelude: asTypeOf :: a -> a -> a
- Language.Fay.Prelude: asin :: Double -> Double
- Language.Fay.Prelude: asinh :: Double -> Double
- Language.Fay.Prelude: atan :: Double -> Double
- Language.Fay.Prelude: atanh :: Double -> Double
- Language.Fay.Prelude: break :: (a -> Bool) -> [a] -> ([a], [a])
- Language.Fay.Prelude: ceiling :: Double -> Int
- Language.Fay.Prelude: class Typeable a => Data a
- Language.Fay.Prelude: class Eq a
- Language.Fay.Prelude: class Monad (m :: * -> *)
- Language.Fay.Prelude: class Read a
- Language.Fay.Prelude: class Show a
- Language.Fay.Prelude: class Typeable a
- Language.Fay.Prelude: compare :: Ord a => a -> a -> Ordering
- Language.Fay.Prelude: concat :: [[a]] -> [a]
- Language.Fay.Prelude: concatMap :: (a -> [b]) -> [a] -> [b]
- Language.Fay.Prelude: const :: a -> b -> a
- Language.Fay.Prelude: cos :: Double -> Double
- Language.Fay.Prelude: cosh :: Double -> Double
- Language.Fay.Prelude: curry :: ((a, b) -> c) -> a -> b -> c
- Language.Fay.Prelude: cycle :: [a] -> [a]
- Language.Fay.Prelude: data Bool :: *
- Language.Fay.Prelude: data Char :: *
- Language.Fay.Prelude: data Double :: *
- Language.Fay.Prelude: data Either a b
- Language.Fay.Prelude: data Fay a
- Language.Fay.Prelude: data Int :: *
- Language.Fay.Prelude: data Integer :: *
- Language.Fay.Prelude: data Maybe a :: * -> *
- Language.Fay.Prelude: data Ordering
- Language.Fay.Prelude: dataCast1 :: (Data a, Typeable1 t) => (forall d. Data d => c (t d)) -> Maybe (c a)
- Language.Fay.Prelude: dataCast2 :: (Data a, Typeable2 t) => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a)
- Language.Fay.Prelude: dataTypeOf :: Data a => a -> DataType
- Language.Fay.Prelude: div :: Int -> Int -> Int
- Language.Fay.Prelude: divMod :: Int -> Int -> (Int, Int)
- Language.Fay.Prelude: drop :: Int -> [a] -> [a]
- Language.Fay.Prelude: dropWhile :: (a -> Bool) -> [a] -> [a]
- Language.Fay.Prelude: either :: (a -> c) -> (b -> c) -> Either a b -> c
- Language.Fay.Prelude: elem :: Eq a => a -> [a] -> Bool
- Language.Fay.Prelude: enumFrom :: Num a => a -> [a]
- Language.Fay.Prelude: enumFromThen :: Num t => t -> t -> [t]
- Language.Fay.Prelude: enumFromThenTo :: (Ord t, Num t) => t -> t -> t -> [t]
- Language.Fay.Prelude: enumFromTo :: (Ord t, Num t) => t -> t -> [t]
- Language.Fay.Prelude: error :: String -> a
- Language.Fay.Prelude: even :: Int -> Bool
- Language.Fay.Prelude: exp :: Double -> Double
- Language.Fay.Prelude: fail :: String -> Fay a
- Language.Fay.Prelude: filter :: (a -> Bool) -> [a] -> [a]
- Language.Fay.Prelude: find :: (a -> Bool) -> [a] -> Maybe a
- Language.Fay.Prelude: flip :: (t1 -> t2 -> t) -> t2 -> t1 -> t
- Language.Fay.Prelude: floor :: Double -> Int
- Language.Fay.Prelude: foldl :: (t1 -> t -> t1) -> t1 -> [t] -> t1
- Language.Fay.Prelude: foldl1 :: (a -> a -> a) -> [a] -> a
- Language.Fay.Prelude: foldr :: (t -> t1 -> t1) -> t1 -> [t] -> t1
- Language.Fay.Prelude: foldr1 :: (a -> a -> a) -> [a] -> a
- Language.Fay.Prelude: forM_ :: Monad m => [t] -> (t -> m a) -> m ()
- Language.Fay.Prelude: force :: a -> Bool -> Fay a
- Language.Fay.Prelude: fromInteger :: a -> a
- Language.Fay.Prelude: fromIntegral :: Int -> Double
- Language.Fay.Prelude: fromRational :: a -> a
- Language.Fay.Prelude: fst :: (t, t1) -> t
- Language.Fay.Prelude: gcd :: Int -> Int -> Int
- Language.Fay.Prelude: gfoldl :: Data a => (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> a -> c a
- Language.Fay.Prelude: gmapM :: (Data a, Monad m) => (forall d. Data d => d -> m d) -> a -> m a
- Language.Fay.Prelude: gmapMo :: (Data a, MonadPlus m) => (forall d. Data d => d -> m d) -> a -> m a
- Language.Fay.Prelude: gmapMp :: (Data a, MonadPlus m) => (forall d. Data d => d -> m d) -> a -> m a
- Language.Fay.Prelude: gmapQ :: Data a => (forall d. Data d => d -> u) -> a -> [u]
- Language.Fay.Prelude: gmapQi :: Data a => Int -> (forall d. Data d => d -> u) -> a -> u
- Language.Fay.Prelude: gmapQl :: Data a => (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r
- Language.Fay.Prelude: gmapQr :: Data a => (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r
- Language.Fay.Prelude: gmapT :: Data a => (forall b. Data b => b -> b) -> a -> a
- Language.Fay.Prelude: gunfold :: Data a => (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c a
- Language.Fay.Prelude: head :: [a] -> a
- Language.Fay.Prelude: id :: a -> a
- Language.Fay.Prelude: init :: [a] -> [a]
- Language.Fay.Prelude: insertBy :: (a -> a -> Ordering) -> a -> [a] -> [a]
- Language.Fay.Prelude: intercalate :: [a] -> [[a]] -> [a]
- Language.Fay.Prelude: intersperse :: a -> [a] -> [a]
- Language.Fay.Prelude: iterate :: (a -> a) -> a -> [a]
- Language.Fay.Prelude: last :: [a] -> a
- Language.Fay.Prelude: lcm :: Int -> Int -> Int
- Language.Fay.Prelude: length :: [a] -> Int
- Language.Fay.Prelude: lines :: String -> [String]
- Language.Fay.Prelude: log :: Double -> Double
- Language.Fay.Prelude: logBase :: Double -> Double -> Double
- Language.Fay.Prelude: lookup :: Eq a1 => a1 -> [(a1, a)] -> Maybe a
- Language.Fay.Prelude: map :: (a -> b) -> [a] -> [b]
- Language.Fay.Prelude: mapM_ :: Monad m => (a -> m b) -> [a] -> m ()
- Language.Fay.Prelude: max :: (Num a, Foreign a) => a -> a -> a
- Language.Fay.Prelude: maximum :: (Num a, Foreign a) => [a] -> a
- Language.Fay.Prelude: maybe :: t -> (t1 -> t) -> Maybe t1 -> t
- Language.Fay.Prelude: min :: (Num a, Foreign a) => a -> a -> a
- Language.Fay.Prelude: minimum :: (Num a, Foreign a) => [a] -> a
- Language.Fay.Prelude: mod :: Int -> Int -> Int
- Language.Fay.Prelude: negate :: Num a => a -> a
- Language.Fay.Prelude: not :: Bool -> Bool
- Language.Fay.Prelude: notElem :: Eq a => a -> [a] -> Bool
- Language.Fay.Prelude: nub :: Eq a => [a] -> [a]
- Language.Fay.Prelude: null :: [t] -> Bool
- Language.Fay.Prelude: odd :: Int -> Bool
- Language.Fay.Prelude: or :: [Bool] -> Bool
- Language.Fay.Prelude: otherwise :: Bool
- Language.Fay.Prelude: pi :: Double
- Language.Fay.Prelude: pred :: Num a => a -> a
- Language.Fay.Prelude: prependToAll :: a -> [a] -> [a]
- Language.Fay.Prelude: print :: Foreign a => Automatic a -> Fay ()
- Language.Fay.Prelude: product :: Num a => [a] -> a
- Language.Fay.Prelude: properFraction :: Double -> (Int, Double)
- Language.Fay.Prelude: putStrLn :: String -> Fay ()
- Language.Fay.Prelude: quot :: Int -> Int -> Int
- Language.Fay.Prelude: quotRem :: Int -> Int -> (Int, Int)
- Language.Fay.Prelude: read :: Read a => String -> a
- Language.Fay.Prelude: recip :: Double -> Double
- Language.Fay.Prelude: rem :: Int -> Int -> Int
- Language.Fay.Prelude: repeat :: a -> [a]
- Language.Fay.Prelude: replicate :: Int -> a -> [a]
- Language.Fay.Prelude: return :: a -> Fay a
- Language.Fay.Prelude: reverse :: [a] -> [a]
- Language.Fay.Prelude: round :: Double -> Int
- Language.Fay.Prelude: scanl :: (a -> b -> a) -> a -> [b] -> [a]
- Language.Fay.Prelude: scanl1 :: (a -> a -> a) -> [a] -> [a]
- Language.Fay.Prelude: scanr :: (a -> b -> b) -> b -> [a] -> [b]
- Language.Fay.Prelude: scanr1 :: (a -> a -> a) -> [a] -> [a]
- Language.Fay.Prelude: seq :: a -> b -> b
- Language.Fay.Prelude: sequence :: Monad m => [m a] -> m [a]
- Language.Fay.Prelude: sequence_ :: Monad m => [m a] -> m ()
- Language.Fay.Prelude: show :: (Foreign a, Show a) => Automatic a -> String
- Language.Fay.Prelude: signum :: (Num a, Ord a) => a -> a
- Language.Fay.Prelude: sin :: Double -> Double
- Language.Fay.Prelude: sinh :: Double -> Double
- Language.Fay.Prelude: snd :: (t, t1) -> t1
- Language.Fay.Prelude: sort :: Ord a => [a] -> [a]
- Language.Fay.Prelude: sortBy :: (t -> t -> Ordering) -> [t] -> [t]
- Language.Fay.Prelude: span :: (a -> Bool) -> [a] -> ([a], [a])
- Language.Fay.Prelude: splitAt :: Int -> [a] -> ([a], [a])
- Language.Fay.Prelude: sqrt :: Double -> Double
- Language.Fay.Prelude: subtract :: Num a => a -> a -> a
- Language.Fay.Prelude: succ :: Num a => a -> a
- Language.Fay.Prelude: sum :: Num a => [a] -> a
- Language.Fay.Prelude: tail :: [a] -> [a]
- Language.Fay.Prelude: take :: Int -> [a] -> [a]
- Language.Fay.Prelude: takeWhile :: (a -> Bool) -> [a] -> [a]
- Language.Fay.Prelude: tan :: Double -> Double
- Language.Fay.Prelude: tanh :: Double -> Double
- Language.Fay.Prelude: toConstr :: Data a => a -> Constr
- Language.Fay.Prelude: truncate :: Double -> Int
- Language.Fay.Prelude: type String = [Char]
- Language.Fay.Prelude: typeOf :: Typeable a => a -> TypeRep
- Language.Fay.Prelude: uncurry :: (a -> b -> c) -> (a, b) -> c
- Language.Fay.Prelude: undefined :: a
- Language.Fay.Prelude: unlines :: [String] -> String
- Language.Fay.Prelude: until :: (a -> Bool) -> (a -> a) -> a -> a
- Language.Fay.Prelude: unwords :: [String] -> String
- Language.Fay.Prelude: unzip :: [(a, b)] -> ([a], [b])
- Language.Fay.Prelude: unzip3 :: [(a, b, c)] -> ([a], [b], [c])
- Language.Fay.Prelude: when :: Monad m => Bool -> m a -> m ()
- Language.Fay.Prelude: words :: String -> [String]
- Language.Fay.Prelude: zip :: [a] -> [b] -> [(a, b)]
- Language.Fay.Prelude: zip3 :: [a] -> [b] -> [c] -> [(a, b, c)]
- Language.Fay.Prelude: zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
- Language.Fay.Prelude: zipWith3 :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
- Language.Fay.Types: Automatic :: FundamentalType
- Language.Fay.Types: BoolType :: FundamentalType
- Language.Fay.Types: Compile :: RWST CompileReader () CompileState (ErrorT CompileError IO) a -> Compile a
- Language.Fay.Types: CompileReader :: CompileConfig -> CompileReader
- Language.Fay.Types: CompileState :: [QName] -> Map ModuleName [QName] -> ModuleName -> FilePath -> [(QName, [QName])] -> [(QName, [QName])] -> [JsStmt] -> [JsStmt] -> [(ModuleName, FilePath)] -> Integer -> Set Name -> ModuleScope -> CompileState
- Language.Fay.Types: Couldn'tFindImport :: ModuleName -> [FilePath] -> CompileError
- Language.Fay.Types: DateType :: FundamentalType
- Language.Fay.Types: Defined :: FundamentalType -> FundamentalType
- Language.Fay.Types: DoubleType :: FundamentalType
- Language.Fay.Types: EmptyDoBlock :: CompileError
- Language.Fay.Types: FfiFormatBadChars :: String -> CompileError
- Language.Fay.Types: FfiFormatIncompleteArg :: CompileError
- Language.Fay.Types: FfiFormatInvalidJavaScript :: SrcLoc -> String -> String -> CompileError
- Language.Fay.Types: FfiFormatNoSuchArg :: Int -> CompileError
- Language.Fay.Types: FfiNeedsTypeSig :: Decl -> CompileError
- Language.Fay.Types: FunctionType :: [FundamentalType] -> FundamentalType
- Language.Fay.Types: IntType :: FundamentalType
- Language.Fay.Types: InvalidDoBlock :: CompileError
- Language.Fay.Types: JsApp :: JsExp -> [JsExp] -> JsExp
- Language.Fay.Types: JsApply :: JsName
- Language.Fay.Types: JsBlock :: [JsStmt] -> JsStmt
- Language.Fay.Types: JsBool :: Bool -> JsLit
- Language.Fay.Types: JsBuiltIn :: Name -> JsName
- Language.Fay.Types: JsChar :: Char -> JsLit
- Language.Fay.Types: JsConstructor :: QName -> JsName
- Language.Fay.Types: JsContinue :: JsStmt
- Language.Fay.Types: JsEarlyReturn :: JsExp -> JsStmt
- Language.Fay.Types: JsEq :: JsExp -> JsExp -> JsExp
- Language.Fay.Types: JsFloating :: Double -> JsLit
- Language.Fay.Types: JsForce :: JsName
- Language.Fay.Types: JsFun :: [JsName] -> [JsStmt] -> (Maybe JsExp) -> JsExp
- Language.Fay.Types: JsGetProp :: JsExp -> JsName -> JsExp
- Language.Fay.Types: JsGetPropExtern :: JsExp -> String -> JsExp
- Language.Fay.Types: JsIf :: JsExp -> [JsStmt] -> [JsStmt] -> JsStmt
- Language.Fay.Types: JsIndex :: Int -> JsExp -> JsExp
- Language.Fay.Types: JsInfix :: String -> JsExp -> JsExp -> JsExp
- Language.Fay.Types: JsInstanceOf :: JsExp -> JsName -> JsExp
- Language.Fay.Types: JsInt :: Int -> JsLit
- Language.Fay.Types: JsList :: [JsExp] -> JsExp
- Language.Fay.Types: JsLit :: JsLit -> JsExp
- Language.Fay.Types: JsLookup :: JsExp -> JsExp -> JsExp
- Language.Fay.Types: JsMappedVar :: SrcLoc -> JsName -> JsExp -> JsStmt
- Language.Fay.Types: JsName :: JsName -> JsExp
- Language.Fay.Types: JsNameVar :: QName -> JsName
- Language.Fay.Types: JsNegApp :: JsExp -> JsExp
- Language.Fay.Types: JsNeq :: JsExp -> JsExp -> JsExp
- Language.Fay.Types: JsNew :: JsName -> [JsExp] -> JsExp
- Language.Fay.Types: JsNull :: JsExp
- Language.Fay.Types: JsObj :: [(String, JsExp)] -> JsExp
- Language.Fay.Types: JsParam :: Integer -> JsName
- Language.Fay.Types: JsParametrizedType :: JsName
- Language.Fay.Types: JsParen :: JsExp -> JsExp
- Language.Fay.Types: JsRawExp :: String -> JsExp
- Language.Fay.Types: JsSetProp :: JsName -> JsName -> JsExp -> JsStmt
- Language.Fay.Types: JsSetPropExtern :: JsName -> JsName -> JsExp -> JsStmt
- Language.Fay.Types: JsStr :: String -> JsLit
- Language.Fay.Types: JsTernaryIf :: JsExp -> JsExp -> JsExp -> JsExp
- Language.Fay.Types: JsThis :: JsName
- Language.Fay.Types: JsThrow :: JsExp -> JsStmt
- Language.Fay.Types: JsThrowExp :: JsExp -> JsExp
- Language.Fay.Types: JsThunk :: JsName
- Language.Fay.Types: JsTmp :: Integer -> JsName
- Language.Fay.Types: JsType :: FundamentalType -> FundamentalType
- Language.Fay.Types: JsUndefined :: JsExp
- Language.Fay.Types: JsUpdate :: JsName -> JsExp -> JsStmt
- Language.Fay.Types: JsUpdateProp :: JsExp -> JsName -> JsExp -> JsExp
- Language.Fay.Types: JsUpdatePropExtern :: JsExp -> JsName -> JsExp -> JsExp
- Language.Fay.Types: JsVar :: JsName -> JsExp -> JsStmt
- Language.Fay.Types: JsWhile :: JsExp -> [JsStmt] -> JsStmt
- Language.Fay.Types: LetUnsupported :: CompileError
- Language.Fay.Types: ListType :: FundamentalType -> FundamentalType
- Language.Fay.Types: Mapping :: String -> SrcLoc -> SrcLoc -> Mapping
- Language.Fay.Types: Nullable :: FundamentalType -> FundamentalType
- Language.Fay.Types: ParseError :: SrcLoc -> String -> CompileError
- Language.Fay.Types: PrintState :: Bool -> Int -> Int -> [Mapping] -> Int -> [String] -> Bool -> PrintState
- Language.Fay.Types: Printer :: State PrintState a -> Printer a
- Language.Fay.Types: PtrType :: FundamentalType
- Language.Fay.Types: RecursiveDoUnsupported :: CompileError
- Language.Fay.Types: SerializeAnywhere :: SerializeContext
- Language.Fay.Types: SerializeUserArg :: Int -> SerializeContext
- Language.Fay.Types: StringType :: FundamentalType
- Language.Fay.Types: TupleType :: [FundamentalType] -> FundamentalType
- Language.Fay.Types: UnableResolveCachedImport :: ModuleName -> CompileError
- Language.Fay.Types: UnableResolveQualified :: QName -> CompileError
- Language.Fay.Types: UnableResolveUnqualified :: Name -> CompileError
- Language.Fay.Types: UnknownType :: FundamentalType
- Language.Fay.Types: UnsupportedDeclaration :: Decl -> CompileError
- Language.Fay.Types: UnsupportedExportSpec :: ExportSpec -> CompileError
- Language.Fay.Types: UnsupportedExpression :: Exp -> CompileError
- Language.Fay.Types: UnsupportedFieldPattern :: PatField -> CompileError
- Language.Fay.Types: UnsupportedGuardedAlts :: GuardedAlts -> CompileError
- Language.Fay.Types: UnsupportedImport :: ImportDecl -> CompileError
- Language.Fay.Types: UnsupportedLetBinding :: Decl -> CompileError
- Language.Fay.Types: UnsupportedLiteral :: Literal -> CompileError
- Language.Fay.Types: UnsupportedMatchSyntax :: Match -> CompileError
- Language.Fay.Types: UnsupportedModuleSyntax :: Module -> CompileError
- Language.Fay.Types: UnsupportedOperator :: QOp -> CompileError
- Language.Fay.Types: UnsupportedPattern :: Pat -> CompileError
- Language.Fay.Types: UnsupportedQualStmt :: QualStmt -> CompileError
- Language.Fay.Types: UnsupportedRhs :: Rhs -> CompileError
- Language.Fay.Types: UnsupportedWhereInAlt :: Alt -> CompileError
- Language.Fay.Types: UnsupportedWhereInMatch :: Match -> CompileError
- Language.Fay.Types: UserDefined :: Name -> [FundamentalType] -> FundamentalType
- Language.Fay.Types: addConfigDirectoryInclude :: FilePath -> CompileConfig -> CompileConfig
- Language.Fay.Types: addConfigDirectoryIncludes :: [FilePath] -> CompileConfig -> CompileConfig
- Language.Fay.Types: addConfigPackage :: String -> CompileConfig -> CompileConfig
- Language.Fay.Types: addConfigPackages :: [String] -> CompileConfig -> CompileConfig
- Language.Fay.Types: class (Parseable from, Printable to) => CompilesTo from to | from -> to
- Language.Fay.Types: class Printable a
- Language.Fay.Types: compileTo :: CompilesTo from to => from -> Compile to
- Language.Fay.Types: configDirectoryIncludes :: CompileConfig -> [FilePath]
- Language.Fay.Types: configPackages :: CompileConfig -> [String]
- Language.Fay.Types: data CompileConfig
- Language.Fay.Types: data CompileError
- Language.Fay.Types: data CompileReader
- Language.Fay.Types: data CompileState
- Language.Fay.Types: data Fay a
- Language.Fay.Types: data FundamentalType
- Language.Fay.Types: data JsExp
- Language.Fay.Types: data JsLit
- Language.Fay.Types: data JsName
- Language.Fay.Types: data JsStmt
- Language.Fay.Types: data Mapping
- Language.Fay.Types: data PrintState
- Language.Fay.Types: data SerializeContext
- Language.Fay.Types: defaultCompileReader :: CompileConfig -> IO CompileReader
- Language.Fay.Types: defaultCompileState :: IO CompileState
- Language.Fay.Types: faySourceDir :: IO FilePath
- Language.Fay.Types: instance Applicative Compile
- Language.Fay.Types: instance Default CompileConfig
- Language.Fay.Types: instance Default PrintState
- Language.Fay.Types: instance Eq JsExp
- Language.Fay.Types: instance Eq JsLit
- Language.Fay.Types: instance Eq JsName
- Language.Fay.Types: instance Eq JsStmt
- Language.Fay.Types: instance Eq SerializeContext
- Language.Fay.Types: instance Error CompileError
- Language.Fay.Types: instance Functor Compile
- Language.Fay.Types: instance Functor Printer
- Language.Fay.Types: instance IsString ModuleName
- Language.Fay.Types: instance IsString Name
- Language.Fay.Types: instance IsString QName
- Language.Fay.Types: instance Monad Compile
- Language.Fay.Types: instance Monad Fay
- Language.Fay.Types: instance Monad Printer
- Language.Fay.Types: instance MonadError CompileError Compile
- Language.Fay.Types: instance MonadIO Compile
- Language.Fay.Types: instance MonadReader CompileReader Compile
- Language.Fay.Types: instance MonadState CompileState Compile
- Language.Fay.Types: instance MonadState PrintState Printer
- Language.Fay.Types: instance Read SerializeContext
- Language.Fay.Types: instance Show CompileConfig
- Language.Fay.Types: instance Show CompileError
- Language.Fay.Types: instance Show CompileReader
- Language.Fay.Types: instance Show CompileState
- Language.Fay.Types: instance Show FundamentalType
- Language.Fay.Types: instance Show JsExp
- Language.Fay.Types: instance Show JsLit
- Language.Fay.Types: instance Show JsName
- Language.Fay.Types: instance Show JsStmt
- Language.Fay.Types: instance Show Mapping
- Language.Fay.Types: instance Show SerializeContext
- Language.Fay.Types: mappingFrom :: Mapping -> SrcLoc
- Language.Fay.Types: mappingName :: Mapping -> String
- Language.Fay.Types: mappingTo :: Mapping -> SrcLoc
- Language.Fay.Types: newtype Compile a
- Language.Fay.Types: newtype Printer a
- Language.Fay.Types: printJS :: Printable a => a -> Printer ()
- Language.Fay.Types: psColumn :: PrintState -> Int
- Language.Fay.Types: psIndentLevel :: PrintState -> Int
- Language.Fay.Types: psLine :: PrintState -> Int
- Language.Fay.Types: psMapping :: PrintState -> [Mapping]
- Language.Fay.Types: psNewline :: PrintState -> Bool
- Language.Fay.Types: psOutput :: PrintState -> [String]
- Language.Fay.Types: psPretty :: PrintState -> Bool
- Language.Fay.Types: readerConfig :: CompileReader -> CompileConfig
- Language.Fay.Types: runPrinter :: Printer a -> State PrintState a
- Language.Fay.Types: stateExports :: CompileState -> [QName]
- Language.Fay.Types: stateExportsCache :: CompileState -> Map ModuleName [QName]
- Language.Fay.Types: stateFayToJs :: CompileState -> [JsStmt]
- Language.Fay.Types: stateFilePath :: CompileState -> FilePath
- Language.Fay.Types: stateImported :: CompileState -> [(ModuleName, FilePath)]
- Language.Fay.Types: stateJsToFay :: CompileState -> [JsStmt]
- Language.Fay.Types: stateLocalScope :: CompileState -> Set Name
- Language.Fay.Types: stateModuleName :: CompileState -> ModuleName
- Language.Fay.Types: stateModuleScope :: CompileState -> ModuleScope
- Language.Fay.Types: stateNameDepth :: CompileState -> Integer
- Language.Fay.Types: stateRecordTypes :: CompileState -> [(QName, [QName])]
- Language.Fay.Types: stateRecords :: CompileState -> [(QName, [QName])]
- Language.Fay.Types: unCompile :: Compile a -> RWST CompileReader () CompileState (ErrorT CompileError IO) a
+ Fay: compileFile :: CompileConfig -> FilePath -> IO (Either CompileError String)
+ Fay: compileFileWithState :: CompileConfig -> FilePath -> IO (Either CompileError (String, CompileState))
+ Fay: compileFromTo :: CompileConfig -> FilePath -> Maybe FilePath -> IO ()
+ Fay: compileFromToAndGenerateHtml :: CompileConfig -> FilePath -> FilePath -> IO (Either CompileError String)
+ Fay: getRuntime :: IO String
+ Fay: showCompileError :: CompileError -> String
+ Fay: toJsName :: String -> String
+ Fay.Compiler: compileDecl :: Bool -> Decl -> Compile [JsStmt]
+ Fay.Compiler: compileExp :: Exp -> Compile JsExp
+ Fay.Compiler: compileForDocs :: Module -> Compile [JsStmt]
+ Fay.Compiler: compileModule :: Bool -> Module -> Compile [JsStmt]
+ Fay.Compiler: compileToAst :: (Show from, Show to, CompilesTo from to) => FilePath -> CompileReader -> CompileState -> (from -> Compile to) -> String -> IO (Either CompileError (to, CompileState, CompileWriter))
+ Fay.Compiler: compileToplevelModule :: Module -> Compile [JsStmt]
+ Fay.Compiler: compileViaStr :: (Show from, Show to, CompilesTo from to) => FilePath -> CompileConfig -> (from -> Compile to) -> String -> IO (Either CompileError (PrintState, CompileState, CompileWriter))
+ Fay.Compiler: instance CompilesTo Module [JsStmt]
+ Fay.Compiler: parseFay :: Parseable ast => FilePath -> String -> ParseResult ast
+ Fay.Compiler: runCompile :: CompileReader -> CompileState -> Compile a -> IO (Either CompileError (a, CompileState, CompileWriter))
+ Fay.Compiler.Config: addConfigDirectoryInclude :: Maybe String -> FilePath -> CompileConfig -> CompileConfig
+ Fay.Compiler.Config: addConfigDirectoryIncludePaths :: [FilePath] -> CompileConfig -> CompileConfig
+ Fay.Compiler.Config: addConfigDirectoryIncludes :: [(Maybe String, FilePath)] -> CompileConfig -> CompileConfig
+ Fay.Compiler.Config: addConfigPackage :: String -> CompileConfig -> CompileConfig
+ Fay.Compiler.Config: addConfigPackages :: [String] -> CompileConfig -> CompileConfig
+ Fay.Compiler.Config: configDirectoryIncludePaths :: CompileConfig -> [FilePath]
+ Fay.Compiler.Config: instance Default CompileConfig
+ Fay.Compiler.Config: nonPackageConfigDirectoryIncludePaths :: CompileConfig -> [FilePath]
+ Fay.Compiler.Debug: compileTestAst :: (Show from, Show to, CompilesTo from to) => CompileConfig -> (from -> Compile to) -> String -> IO ()
+ Fay.Compiler.Debug: debug :: (Show from, Show to, CompilesTo from to) => (from -> Compile to) -> String -> IO ()
+ Fay.Compiler.Debug: printCompile :: (Show from, Show to, CompilesTo from to) => CompileConfig -> (from -> Compile to) -> String -> IO ()
+ Fay.Compiler.Debug: printTestCompile :: String -> IO ()
+ Fay.Convert: readFromFay :: Data a => Value -> Maybe a
+ Fay.Convert: showToFay :: Show a => a -> Maybe Value
+ Fay.Types: Automatic :: FundamentalType
+ Fay.Types: BoolType :: FundamentalType
+ Fay.Types: Compile :: RWST CompileReader CompileWriter CompileState (ErrorT CompileError IO) a -> Compile a
+ Fay.Types: CompileConfig :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> [(Maybe String, FilePath)] -> Bool -> Bool -> [FilePath] -> Bool -> Bool -> Maybe FilePath -> Bool -> Bool -> Bool -> Maybe FilePath -> [String] -> CompileConfig
+ Fay.Types: CompileReader :: CompileConfig -> (Literal -> Compile JsExp) -> (Bool -> [Decl] -> Compile [JsStmt]) -> CompileReader
+ Fay.Types: CompileState :: Map ModuleName (Set QName) -> FilePath -> [(QName, [QName])] -> [(QName, [QName])] -> [(ModuleName, FilePath)] -> Integer -> Set Name -> ModuleScope -> ModuleName -> CompileState
+ Fay.Types: CompileWriter :: [JsStmt] -> [JsStmt] -> [JsStmt] -> CompileWriter
+ Fay.Types: Couldn'tFindImport :: ModuleName -> [FilePath] -> CompileError
+ Fay.Types: DateType :: FundamentalType
+ Fay.Types: Defined :: FundamentalType -> FundamentalType
+ Fay.Types: DoubleType :: FundamentalType
+ Fay.Types: EmptyDoBlock :: CompileError
+ Fay.Types: FfiFormatBadChars :: String -> CompileError
+ Fay.Types: FfiFormatIncompleteArg :: CompileError
+ Fay.Types: FfiFormatInvalidJavaScript :: SrcLoc -> String -> String -> CompileError
+ Fay.Types: FfiFormatNoSuchArg :: Int -> CompileError
+ Fay.Types: FfiNeedsTypeSig :: Decl -> CompileError
+ Fay.Types: FunctionType :: [FundamentalType] -> FundamentalType
+ Fay.Types: IntType :: FundamentalType
+ Fay.Types: InvalidDoBlock :: CompileError
+ Fay.Types: JsApp :: JsExp -> [JsExp] -> JsExp
+ Fay.Types: JsApply :: JsName
+ Fay.Types: JsBlock :: [JsStmt] -> JsStmt
+ Fay.Types: JsBool :: Bool -> JsLit
+ Fay.Types: JsBuiltIn :: Name -> JsName
+ Fay.Types: JsChar :: Char -> JsLit
+ Fay.Types: JsConstructor :: QName -> JsName
+ Fay.Types: JsContinue :: JsStmt
+ Fay.Types: JsEarlyReturn :: JsExp -> JsStmt
+ Fay.Types: JsEq :: JsExp -> JsExp -> JsExp
+ Fay.Types: JsFloating :: Double -> JsLit
+ Fay.Types: JsForce :: JsName
+ Fay.Types: JsFun :: [JsName] -> [JsStmt] -> (Maybe JsExp) -> JsExp
+ Fay.Types: JsGetProp :: JsExp -> JsName -> JsExp
+ Fay.Types: JsGetPropExtern :: JsExp -> String -> JsExp
+ Fay.Types: JsIf :: JsExp -> [JsStmt] -> [JsStmt] -> JsStmt
+ Fay.Types: JsIndex :: Int -> JsExp -> JsExp
+ Fay.Types: JsInfix :: String -> JsExp -> JsExp -> JsExp
+ Fay.Types: JsInstanceOf :: JsExp -> JsName -> JsExp
+ Fay.Types: JsInt :: Int -> JsLit
+ Fay.Types: JsList :: [JsExp] -> JsExp
+ Fay.Types: JsLit :: JsLit -> JsExp
+ Fay.Types: JsLookup :: JsExp -> JsExp -> JsExp
+ Fay.Types: JsMappedVar :: SrcLoc -> JsName -> JsExp -> JsStmt
+ Fay.Types: JsName :: JsName -> JsExp
+ Fay.Types: JsNameVar :: QName -> JsName
+ Fay.Types: JsNegApp :: JsExp -> JsExp
+ Fay.Types: JsNeq :: JsExp -> JsExp -> JsExp
+ Fay.Types: JsNew :: JsName -> [JsExp] -> JsExp
+ Fay.Types: JsNull :: JsExp
+ Fay.Types: JsObj :: [(String, JsExp)] -> JsExp
+ Fay.Types: JsParam :: Integer -> JsName
+ Fay.Types: JsParametrizedType :: JsName
+ Fay.Types: JsParen :: JsExp -> JsExp
+ Fay.Types: JsRawExp :: String -> JsExp
+ Fay.Types: JsSeq :: [JsExp] -> JsExp
+ Fay.Types: JsSetProp :: JsName -> JsName -> JsExp -> JsStmt
+ Fay.Types: JsSetPropExtern :: JsName -> JsName -> JsExp -> JsStmt
+ Fay.Types: JsStr :: String -> JsLit
+ Fay.Types: JsTernaryIf :: JsExp -> JsExp -> JsExp -> JsExp
+ Fay.Types: JsThis :: JsName
+ Fay.Types: JsThrow :: JsExp -> JsStmt
+ Fay.Types: JsThrowExp :: JsExp -> JsExp
+ Fay.Types: JsThunk :: JsName
+ Fay.Types: JsTmp :: Integer -> JsName
+ Fay.Types: JsType :: FundamentalType -> FundamentalType
+ Fay.Types: JsUndefined :: JsExp
+ Fay.Types: JsUpdate :: JsName -> JsExp -> JsStmt
+ Fay.Types: JsUpdateProp :: JsExp -> JsName -> JsExp -> JsExp
+ Fay.Types: JsUpdatePropExtern :: JsExp -> JsName -> JsExp -> JsExp
+ Fay.Types: JsVar :: JsName -> JsExp -> JsStmt
+ Fay.Types: JsWhile :: JsExp -> [JsStmt] -> JsStmt
+ Fay.Types: LetUnsupported :: CompileError
+ Fay.Types: ListType :: FundamentalType -> FundamentalType
+ Fay.Types: Mapping :: String -> SrcLoc -> SrcLoc -> Mapping
+ Fay.Types: Nullable :: FundamentalType -> FundamentalType
+ Fay.Types: ParseError :: SrcLoc -> String -> CompileError
+ Fay.Types: PrintState :: Bool -> Int -> Int -> [Mapping] -> Int -> [String] -> Bool -> PrintState
+ Fay.Types: Printer :: State PrintState a -> Printer a
+ Fay.Types: PtrType :: FundamentalType
+ Fay.Types: RecursiveDoUnsupported :: CompileError
+ Fay.Types: SerializeAnywhere :: SerializeContext
+ Fay.Types: SerializeUserArg :: Int -> SerializeContext
+ Fay.Types: StringType :: FundamentalType
+ Fay.Types: TupleType :: [FundamentalType] -> FundamentalType
+ Fay.Types: UnableResolveQualified :: QName -> CompileError
+ Fay.Types: UnableResolveUnqualified :: Name -> CompileError
+ Fay.Types: UnknownType :: FundamentalType
+ Fay.Types: UnsupportedDeclaration :: Decl -> CompileError
+ Fay.Types: UnsupportedExportSpec :: ExportSpec -> CompileError
+ Fay.Types: UnsupportedExpression :: Exp -> CompileError
+ Fay.Types: UnsupportedFieldPattern :: PatField -> CompileError
+ Fay.Types: UnsupportedGuardedAlts :: GuardedAlts -> CompileError
+ Fay.Types: UnsupportedImport :: ImportDecl -> CompileError
+ Fay.Types: UnsupportedLetBinding :: Decl -> CompileError
+ Fay.Types: UnsupportedLiteral :: Literal -> CompileError
+ Fay.Types: UnsupportedMatchSyntax :: Match -> CompileError
+ Fay.Types: UnsupportedModuleSyntax :: Module -> CompileError
+ Fay.Types: UnsupportedOperator :: QOp -> CompileError
+ Fay.Types: UnsupportedPattern :: Pat -> CompileError
+ Fay.Types: UnsupportedQualStmt :: QualStmt -> CompileError
+ Fay.Types: UnsupportedRhs :: Rhs -> CompileError
+ Fay.Types: UnsupportedWhereInAlt :: Alt -> CompileError
+ Fay.Types: UnsupportedWhereInMatch :: Match -> CompileError
+ Fay.Types: UserDefined :: Name -> [FundamentalType] -> FundamentalType
+ Fay.Types: _stateExports :: CompileState -> Map ModuleName (Set QName)
+ Fay.Types: addCurrentExport :: QName -> CompileState -> CompileState
+ Fay.Types: class (Parseable from, Printable to) => CompilesTo from to | from -> to
+ Fay.Types: class Printable a
+ Fay.Types: compileTo :: CompilesTo from to => from -> Compile to
+ Fay.Types: configDirectoryIncludes :: CompileConfig -> [(Maybe String, FilePath)]
+ Fay.Types: configDispatcherOnly :: CompileConfig -> Bool
+ Fay.Types: configDispatchers :: CompileConfig -> Bool
+ Fay.Types: configExportBuiltins :: CompileConfig -> Bool
+ Fay.Types: configExportRuntime :: CompileConfig -> Bool
+ Fay.Types: configExportStdlib :: CompileConfig -> Bool
+ Fay.Types: configExportStdlibOnly :: CompileConfig -> Bool
+ Fay.Types: configFilePath :: CompileConfig -> Maybe FilePath
+ Fay.Types: configFlattenApps :: CompileConfig -> Bool
+ Fay.Types: configGClosure :: CompileConfig -> Bool
+ Fay.Types: configHtmlJSLibs :: CompileConfig -> [FilePath]
+ Fay.Types: configHtmlWrapper :: CompileConfig -> Bool
+ Fay.Types: configLibrary :: CompileConfig -> Bool
+ Fay.Types: configNaked :: CompileConfig -> Bool
+ Fay.Types: configOptimize :: CompileConfig -> Bool
+ Fay.Types: configPackageConf :: CompileConfig -> Maybe FilePath
+ Fay.Types: configPackages :: CompileConfig -> [String]
+ Fay.Types: configPrettyPrint :: CompileConfig -> Bool
+ Fay.Types: configTypecheck :: CompileConfig -> Bool
+ Fay.Types: configWall :: CompileConfig -> Bool
+ Fay.Types: configWarn :: CompileConfig -> Bool
+ Fay.Types: data CompileConfig
+ Fay.Types: data CompileError
+ Fay.Types: data CompileReader
+ Fay.Types: data CompileState
+ Fay.Types: data CompileWriter
+ Fay.Types: data Fay a
+ Fay.Types: data FundamentalType
+ Fay.Types: data JsExp
+ Fay.Types: data JsLit
+ Fay.Types: data JsName
+ Fay.Types: data JsStmt
+ Fay.Types: data Mapping
+ Fay.Types: data PrintState
+ Fay.Types: data SerializeContext
+ Fay.Types: faySourceDir :: IO FilePath
+ Fay.Types: getCurrentExports :: CompileState -> Set QName
+ Fay.Types: getExportsFor :: ModuleName -> CompileState -> Set QName
+ Fay.Types: instance Applicative Compile
+ Fay.Types: instance Default PrintState
+ Fay.Types: instance Eq JsExp
+ Fay.Types: instance Eq JsLit
+ Fay.Types: instance Eq JsName
+ Fay.Types: instance Eq JsStmt
+ Fay.Types: instance Eq SerializeContext
+ Fay.Types: instance Error CompileError
+ Fay.Types: instance Functor Compile
+ Fay.Types: instance Functor Printer
+ Fay.Types: instance IsString JsLit
+ Fay.Types: instance IsString ModuleName
+ Fay.Types: instance IsString Name
+ Fay.Types: instance IsString QName
+ Fay.Types: instance Monad Compile
+ Fay.Types: instance Monad Fay
+ Fay.Types: instance Monad Printer
+ Fay.Types: instance MonadError CompileError Compile
+ Fay.Types: instance MonadIO Compile
+ Fay.Types: instance MonadReader CompileReader Compile
+ Fay.Types: instance MonadState CompileState Compile
+ Fay.Types: instance MonadState PrintState Printer
+ Fay.Types: instance MonadWriter CompileWriter Compile
+ Fay.Types: instance Monoid CompileWriter
+ Fay.Types: instance Read SerializeContext
+ Fay.Types: instance Show CompileConfig
+ Fay.Types: instance Show CompileError
+ Fay.Types: instance Show CompileState
+ Fay.Types: instance Show CompileWriter
+ Fay.Types: instance Show FundamentalType
+ Fay.Types: instance Show JsExp
+ Fay.Types: instance Show JsLit
+ Fay.Types: instance Show JsName
+ Fay.Types: instance Show JsStmt
+ Fay.Types: instance Show Mapping
+ Fay.Types: instance Show SerializeContext
+ Fay.Types: mappingFrom :: Mapping -> SrcLoc
+ Fay.Types: mappingName :: Mapping -> String
+ Fay.Types: mappingTo :: Mapping -> SrcLoc
+ Fay.Types: newtype Compile a
+ Fay.Types: newtype Printer a
+ Fay.Types: printJS :: Printable a => a -> Printer ()
+ Fay.Types: psColumn :: PrintState -> Int
+ Fay.Types: psIndentLevel :: PrintState -> Int
+ Fay.Types: psLine :: PrintState -> Int
+ Fay.Types: psMapping :: PrintState -> [Mapping]
+ Fay.Types: psNewline :: PrintState -> Bool
+ Fay.Types: psOutput :: PrintState -> [String]
+ Fay.Types: psPretty :: PrintState -> Bool
+ Fay.Types: readerCompileDecls :: CompileReader -> Bool -> [Decl] -> Compile [JsStmt]
+ Fay.Types: readerCompileLit :: CompileReader -> Literal -> Compile JsExp
+ Fay.Types: readerConfig :: CompileReader -> CompileConfig
+ Fay.Types: runPrinter :: Printer a -> State PrintState a
+ Fay.Types: stateFilePath :: CompileState -> FilePath
+ Fay.Types: stateImported :: CompileState -> [(ModuleName, FilePath)]
+ Fay.Types: stateLocalScope :: CompileState -> Set Name
+ Fay.Types: stateModuleName :: CompileState -> ModuleName
+ Fay.Types: stateModuleScope :: CompileState -> ModuleScope
+ Fay.Types: stateNameDepth :: CompileState -> Integer
+ Fay.Types: stateRecordTypes :: CompileState -> [(QName, [QName])]
+ Fay.Types: stateRecords :: CompileState -> [(QName, [QName])]
+ Fay.Types: unCompile :: Compile a -> RWST CompileReader CompileWriter CompileState (ErrorT CompileError IO) a
+ Fay.Types: writerCons :: CompileWriter -> [JsStmt]
+ Fay.Types: writerFayToJs :: CompileWriter -> [JsStmt]
+ Fay.Types: writerJsToFay :: CompileWriter -> [JsStmt]
Files
- docs/analytics.js +0/−13
- docs/beautify.js +0/−1325
- docs/highlight.pack.js +0/−1
- docs/home.css +0/−143
- docs/home.hs +0/−230
- docs/jquery.js +0/−4
- docs/snippets/conditions.hs +0/−9
- docs/snippets/data.hs +0/−11
- docs/snippets/declarations.hs +0/−5
- docs/snippets/dom.hs +0/−16
- docs/snippets/enums.hs +0/−18
- docs/snippets/ffi.hs +0/−17
- docs/snippets/functions.hs +0/−3
- docs/snippets/lists.hs +0/−9
- docs/snippets/patterns.hs +0/−11
- docs/snippets/tail.hs +0/−4
- examples/alert.hs +2/−2
- examples/canvaswater.hs +2/−2
- examples/console.hs +10/−2
- examples/data.hs +2/−2
- examples/dom.hs +2/−2
- examples/ref.hs +2/−2
- examples/tailrecursive.hs +2/−2
- fay.cabal +30/−84
- js/runtime.js +264/−281
- src/Control/Monad/Extra.hs +31/−0
- src/Control/Monad/IO.hs +3/−0
- src/Data/List/Extra.hs +4/−0
- src/Docs.hs +0/−320
- src/Fay.hs +187/−0
- src/Fay/Compiler.hs +224/−0
- src/Fay/Compiler/CollectRecords.hs +118/−0
- src/Fay/Compiler/Config.hs +65/−0
- src/Fay/Compiler/Debug.hs +61/−0
- src/Fay/Compiler/Decl.hs +204/−0
- src/Fay/Compiler/Defaults.hs +42/−0
- src/Fay/Compiler/Exp.hs +404/−0
- src/Fay/Compiler/FFI.hs +357/−0
- src/Fay/Compiler/Misc.hs +337/−0
- src/Fay/Compiler/ModuleScope.hs +140/−0
- src/Fay/Compiler/Optimizer.hs +268/−0
- src/Fay/Compiler/Packages.hs +76/−0
- src/Fay/Compiler/Pattern.hs +162/−0
- src/Fay/Compiler/Print.hs +291/−0
- src/Fay/Compiler/Typecheck.hs +42/−0
- src/Fay/Convert.hs +198/−0
- src/Fay/Types.hs +339/−0
- src/Language/Fay.hs +0/−175
- src/Language/Fay/Compiler.hs +0/−1162
- src/Language/Fay/Compiler/FFI.hs +0/−322
- src/Language/Fay/Compiler/Misc.hs +0/−246
- src/Language/Fay/Compiler/Optimizer.hs +0/−206
- src/Language/Fay/Compiler/Packages.hs +0/−115
- src/Language/Fay/Convert.hs +0/−198
- src/Language/Fay/FFI.hs +3/−45
- src/Language/Fay/ModuleScope.hs +0/−140
- src/Language/Fay/Prelude.hs +0/−59
- src/Language/Fay/Print.hs +0/−287
- src/Language/Fay/Stdlib.hs +0/−735
- src/Language/Fay/Types.hs +0/−362
- src/Main.hs +69/−42
- src/Test/Api.hs +10/−3
- src/Test/Convert.hs +1/−1
- src/Tests.hs +4/−2
- src/Text/Blaze/Extra.hs +0/−34
- tests/Api/CPPTypecheck.hs +13/−0
- tests/List.hs +1/−1
- tests/List2.hs +1/−1
- tests/RecDecl.hs +1/−1
- tests/mutableReference.hs +1/−1
- tests/patternGuards.hs +1/−1
- tests/serialization +17/−0
- tests/serialization.hs +42/−0
- tests/tailRecursion +1/−1
- tests/tailRecursion.hs +1/−2
− docs/analytics.js
@@ -1,13 +0,0 @@-<script type="text/javascript">-if (window.location.href.match(/fay\-lang\.org/)) {- var _gaq = _gaq || [];- _gaq.push(['_setAccount', 'UA-33582139-1']);- _gaq.push(['_trackPageview']);- (function() {- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);- })();-}--</script>
− docs/beautify.js
@@ -1,1325 +0,0 @@-/*jslint onevar: false, plusplus: false */-/*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */-/*-- JS Beautifier------------------- Written by Einar Lielmanis, <einar@jsbeautifier.org>- http://jsbeautifier.org/-- Originally converted to javascript by Vital, <vital76@gmail.com>- "End braces on own line" added by Chris J. Shull, <chrisjshull@gmail.com>-- You are free to use this in any way you want, in case you find this useful or working for you.-- Usage:- js_beautify(js_source_text);- js_beautify(js_source_text, options);-- The options are:- indent_size (default 4) - indentation size,- indent_char (default space) - character to indent with,- preserve_newlines (default true) - whether existing line breaks should be preserved,- preserve_max_newlines (default unlimited) - maximum number of line breaks to be preserved in one chunk,-- jslint_happy (default false) - if true, then jslint-stricter mode is enforced.-- jslint_happy !jslint_happy- ---------------------------------- function () function()-- brace_style (default "collapse") - "collapse" | "expand" | "end-expand" | "expand-strict"- put braces on the same line as control statements (default), or put braces on own line (Allman / ANSI style), or just put end braces on own line.-- expand-strict: put brace on own line even in such cases:-- var a =- {- a: 5,- b: 6- }- This mode may break your scripts - e.g "return { a: 1 }" will be broken into two lines, so beware.-- space_before_conditional (default true) - should the space before conditional statement be added, "if(true)" vs "if (true)",-- unescape_strings (default false) - should printable characters in strings encoded in \xNN notation be unescaped, "example" vs "\x65\x78\x61\x6d\x70\x6c\x65"-- e.g-- js_beautify(js_source_text, {- 'indent_size': 1,- 'indent_char': '\t'- });---*/----function $jsBeautify(source,indentSize) {- return js_beautify(source, { indent_size: indentSize });-}--function js_beautify(js_source_text, options) {-- var input, output, token_text, last_type, last_text, last_last_text, last_word, flags, flag_store, indent_string;- var whitespace, wordchar, punct, parser_pos, line_starters, digits;- var prefix, token_type, do_block_just_closed;- var wanted_newline, just_added_newline, n_newlines;- var preindent_string = '';--- // Some interpreters have unexpected results with foo = baz || bar;- options = options ? options : {};-- var opt_brace_style;-- // compatibility- if (options.space_after_anon_function !== undefined && options.jslint_happy === undefined) {- options.jslint_happy = options.space_after_anon_function;- }- if (options.braces_on_own_line !== undefined) { //graceful handling of deprecated option- opt_brace_style = options.braces_on_own_line ? "expand" : "collapse";- }- opt_brace_style = options.brace_style ? options.brace_style : (opt_brace_style ? opt_brace_style : "collapse");--- var opt_indent_size = options.indent_size ? options.indent_size : 4;- var opt_indent_char = options.indent_char ? options.indent_char : ' ';- var opt_preserve_newlines = typeof options.preserve_newlines === 'undefined' ? true : options.preserve_newlines;- var opt_max_preserve_newlines = typeof options.max_preserve_newlines === 'undefined' ? false : options.max_preserve_newlines;- var opt_jslint_happy = options.jslint_happy === 'undefined' ? false : options.jslint_happy;- var opt_keep_array_indentation = typeof options.keep_array_indentation === 'undefined' ? false : options.keep_array_indentation;- var opt_space_before_conditional = typeof options.space_before_conditional === 'undefined' ? true : options.space_before_conditional;- var opt_indent_case = typeof options.indent_case === 'undefined' ? false : options.indent_case;- var opt_unescape_strings = typeof options.unescape_strings === 'undefined' ? false : options.unescape_strings;-- just_added_newline = false;-- // cache the source's length.- var input_length = js_source_text.length;-- function trim_output(eat_newlines) {- eat_newlines = typeof eat_newlines === 'undefined' ? false : eat_newlines;- while (output.length && (output[output.length - 1] === ' '- || output[output.length - 1] === indent_string- || output[output.length - 1] === preindent_string- || (eat_newlines && (output[output.length - 1] === '\n' || output[output.length - 1] === '\r')))) {- output.pop();- }- }-- function trim(s) {- return s.replace(/^\s\s*|\s\s*$/, '');- }-- // we could use just string.split, but- // IE doesn't like returning empty strings- function split_newlines(s) {- //return s.split(/\x0d\x0a|\x0a/);-- s = s.replace(/\x0d/g, '');- var out = [],- idx = s.indexOf("\n");- while (idx !== -1) {- out.push(s.substring(0, idx));- s = s.substring(idx + 1);- idx = s.indexOf("\n");- }- if (s.length) {- out.push(s);- }- return out;- }-- function force_newline() {- var old_keep_array_indentation = opt_keep_array_indentation;- opt_keep_array_indentation = false;- print_newline();- opt_keep_array_indentation = old_keep_array_indentation;- }-- function print_newline(ignore_repeated) {-- flags.eat_next_space = false;- if (opt_keep_array_indentation && is_array(flags.mode)) {- return;- }-- ignore_repeated = typeof ignore_repeated === 'undefined' ? true : ignore_repeated;-- flags.if_line = false;- trim_output();-- if (!output.length) {- return; // no newline on start of file- }-- if (output[output.length - 1] !== "\n" || !ignore_repeated) {- just_added_newline = true;- output.push("\n");- }- if (preindent_string) {- output.push(preindent_string);- }- for (var i = 0; i < flags.indentation_level; i += 1) {- output.push(indent_string);- }- if (flags.var_line && flags.var_line_reindented) {- output.push(indent_string); // skip space-stuffing, if indenting with a tab- }- if (flags.case_body) {- output.push(indent_string);- }- }---- function print_single_space() {-- if (last_type === 'TK_COMMENT') {- return print_newline();- }- if (flags.eat_next_space) {- flags.eat_next_space = false;- return;- }- var last_output = ' ';- if (output.length) {- last_output = output[output.length - 1];- }- if (last_output !== ' ' && last_output !== '\n' && last_output !== indent_string) { // prevent occassional duplicate space- output.push(' ');- }- }--- function print_token() {- just_added_newline = false;- flags.eat_next_space = false;- output.push(token_text);- }-- function indent() {- flags.indentation_level += 1;- }--- function remove_indent() {- if (output.length && output[output.length - 1] === indent_string) {- output.pop();- }- }-- function set_mode(mode) {- if (flags) {- flag_store.push(flags);- }- flags = {- previous_mode: flags ? flags.mode : 'BLOCK',- mode: mode,- var_line: false,- var_line_tainted: false,- var_line_reindented: false,- in_html_comment: false,- if_line: false,- in_case_statement: false, // switch(..){ INSIDE HERE }- in_case: false, // we're on the exact line with "case 0:"- case_body: false, // the indented case-action block- eat_next_space: false,- indentation_baseline: -1,- indentation_level: (flags ? flags.indentation_level + (flags.case_body ? 1 : 0) + ((flags.var_line && flags.var_line_reindented) ? 1 : 0) : 0),- ternary_depth: 0- };- }-- function is_array(mode) {- return mode === '[EXPRESSION]' || mode === '[INDENTED-EXPRESSION]';- }-- function is_expression(mode) {- return in_array(mode, ['[EXPRESSION]', '(EXPRESSION)', '(FOR-EXPRESSION)', '(COND-EXPRESSION)']);- }-- function restore_mode() {- do_block_just_closed = flags.mode === 'DO_BLOCK';- if (flag_store.length > 0) {- var mode = flags.mode;- flags = flag_store.pop();- flags.previous_mode = mode;- }- }-- function all_lines_start_with(lines, c) {- for (var i = 0; i < lines.length; i++) {- var line = trim(lines[i]);- if (line.charAt(0) !== c) {- return false;- }- }- return true;- }-- function is_special_word(word) {- return in_array(word, ['case', 'return', 'do', 'if', 'throw', 'else']);- }-- function in_array(what, arr) {- for (var i = 0; i < arr.length; i += 1) {- if (arr[i] === what) {- return true;- }- }- return false;- }-- function look_up(exclude) {- var local_pos = parser_pos;- var c = input.charAt(local_pos);- while (in_array(c, whitespace) && c !== exclude) {- local_pos++;- if (local_pos >= input_length) {- return 0;- }- c = input.charAt(local_pos);- }- return c;- }-- function get_next_token() {- var i;- var resulting_string;-- n_newlines = 0;-- if (parser_pos >= input_length) {- return ['', 'TK_EOF'];- }-- wanted_newline = false;-- var c = input.charAt(parser_pos);- parser_pos += 1;--- var keep_whitespace = opt_keep_array_indentation && is_array(flags.mode);-- if (keep_whitespace) {-- //- // slight mess to allow nice preservation of array indentation and reindent that correctly- // first time when we get to the arrays:- // var a = [- // ....'something'- // we make note of whitespace_count = 4 into flags.indentation_baseline- // so we know that 4 whitespaces in original source match indent_level of reindented source- //- // and afterwards, when we get to- // 'something,- // .......'something else'- // we know that this should be indented to indent_level + (7 - indentation_baseline) spaces- //- var whitespace_count = 0;-- while (in_array(c, whitespace)) {-- if (c === "\n") {- trim_output();- output.push("\n");- just_added_newline = true;- whitespace_count = 0;- } else {- if (c === '\t') {- whitespace_count += 4;- } else if (c === '\r') {- // nothing- } else {- whitespace_count += 1;- }- }-- if (parser_pos >= input_length) {- return ['', 'TK_EOF'];- }-- c = input.charAt(parser_pos);- parser_pos += 1;-- }- if (flags.indentation_baseline === -1) {- flags.indentation_baseline = whitespace_count;- }-- if (just_added_newline) {- for (i = 0; i < flags.indentation_level + 1; i += 1) {- output.push(indent_string);- }- if (flags.indentation_baseline !== -1) {- for (i = 0; i < whitespace_count - flags.indentation_baseline; i++) {- output.push(' ');- }- }- }-- } else {- while (in_array(c, whitespace)) {-- if (c === "\n") {- n_newlines += ((opt_max_preserve_newlines) ? (n_newlines <= opt_max_preserve_newlines) ? 1 : 0 : 1);- }--- if (parser_pos >= input_length) {- return ['', 'TK_EOF'];- }-- c = input.charAt(parser_pos);- parser_pos += 1;-- }-- if (opt_preserve_newlines) {- if (n_newlines > 1) {- for (i = 0; i < n_newlines; i += 1) {- print_newline(i === 0);- just_added_newline = true;- }- }- }- wanted_newline = n_newlines > 0;- }--- if (in_array(c, wordchar)) {- if (parser_pos < input_length) {- while (in_array(input.charAt(parser_pos), wordchar)) {- c += input.charAt(parser_pos);- parser_pos += 1;- if (parser_pos === input_length) {- break;- }- }- }-- // small and surprisingly unugly hack for 1E-10 representation- if (parser_pos !== input_length && c.match(/^[0-9]+[Ee]$/) && (input.charAt(parser_pos) === '-' || input.charAt(parser_pos) === '+')) {-- var sign = input.charAt(parser_pos);- parser_pos += 1;-- var t = get_next_token(parser_pos);- c += sign + t[0];- return [c, 'TK_WORD'];- }-- if (c === 'in') { // hack for 'in' operator- return [c, 'TK_OPERATOR'];- }- if (wanted_newline && last_type !== 'TK_OPERATOR'- && last_type !== 'TK_EQUALS'- && !flags.if_line && (opt_preserve_newlines || last_text !== 'var')) {- print_newline();- }- return [c, 'TK_WORD'];- }-- if (c === '(' || c === '[') {- return [c, 'TK_START_EXPR'];- }-- if (c === ')' || c === ']') {- return [c, 'TK_END_EXPR'];- }-- if (c === '{') {- return [c, 'TK_START_BLOCK'];- }-- if (c === '}') {- return [c, 'TK_END_BLOCK'];- }-- if (c === ';') {- return [c, 'TK_SEMICOLON'];- }-- if (c === '/') {- var comment = '';- // peek for comment /* ... */- var inline_comment = true;- if (input.charAt(parser_pos) === '*') {- parser_pos += 1;- if (parser_pos < input_length) {- while (parser_pos < input_length &&- ! (input.charAt(parser_pos) === '*' && input.charAt(parser_pos + 1) && input.charAt(parser_pos + 1) === '/')) {- c = input.charAt(parser_pos);- comment += c;- if (c === "\n" || c === "\r") {- inline_comment = false;- }- parser_pos += 1;- if (parser_pos >= input_length) {- break;- }- }- }- parser_pos += 2;- if (inline_comment && n_newlines === 0) {- return ['/*' + comment + '*/', 'TK_INLINE_COMMENT'];- } else {- return ['/*' + comment + '*/', 'TK_BLOCK_COMMENT'];- }- }- // peek for comment // ...- if (input.charAt(parser_pos) === '/') {- comment = c;- while (input.charAt(parser_pos) !== '\r' && input.charAt(parser_pos) !== '\n') {- comment += input.charAt(parser_pos);- parser_pos += 1;- if (parser_pos >= input_length) {- break;- }- }- if (wanted_newline) {- print_newline();- }- return [comment, 'TK_COMMENT'];- }-- }-- if (c === "'" || // string- c === '"' || // string- (c === '/' &&- ((last_type === 'TK_WORD' && is_special_word(last_text)) ||- (last_text === ')' && in_array(flags.previous_mode, ['(COND-EXPRESSION)', '(FOR-EXPRESSION)'])) ||- (last_type === 'TK_COMMA' || last_type === 'TK_COMMENT' || last_type === 'TK_START_EXPR' || last_type === 'TK_START_BLOCK' || last_type === 'TK_END_BLOCK' || last_type === 'TK_OPERATOR' || last_type === 'TK_EQUALS' || last_type === 'TK_EOF' || last_type === 'TK_SEMICOLON')))) { // regexp- var sep = c;- var esc = false;- var esc1 = 0;- var esc2 = 0;- resulting_string = c;-- if (parser_pos < input_length) {- if (sep === '/') {- //- // handle regexp separately...- //- var in_char_class = false;- while (esc || in_char_class || input.charAt(parser_pos) !== sep) {- resulting_string += input.charAt(parser_pos);- if (!esc) {- esc = input.charAt(parser_pos) === '\\';- if (input.charAt(parser_pos) === '[') {- in_char_class = true;- } else if (input.charAt(parser_pos) === ']') {- in_char_class = false;- }- } else {- esc = false;- }- parser_pos += 1;- if (parser_pos >= input_length) {- // incomplete string/rexp when end-of-file reached.- // bail out with what had been received so far.- return [resulting_string, 'TK_STRING'];- }- }-- } else {- //- // and handle string also separately- //- while (esc || input.charAt(parser_pos) !== sep) {- resulting_string += input.charAt(parser_pos);- if (esc1 && esc1 >= esc2) {- esc1 = parseInt(resulting_string.substr(-esc2), 16);- if (esc1 && esc1 >= 0x20 && esc1 <= 0x7e) {- esc1 = String.fromCharCode(esc1);- resulting_string = resulting_string.substr(0, resulting_string.length - esc2 - 2) + (((esc1 === sep) || (esc1 === '\\')) ? '\\' : '') + esc1;- }- esc1 = 0;- }- if (esc1) {- esc1++;- } else if (!esc) {- esc = input.charAt(parser_pos) === '\\';- } else {- esc = false;- if (opt_unescape_strings) {- if (input.charAt(parser_pos) === 'x') {- esc1++;- esc2 = 2;- } else if (input.charAt(parser_pos) === 'u') {- esc1++;- esc2 = 4;- }- }- }- parser_pos += 1;- if (parser_pos >= input_length) {- // incomplete string/rexp when end-of-file reached.- // bail out with what had been received so far.- return [resulting_string, 'TK_STRING'];- }- }- }---- }-- parser_pos += 1;-- resulting_string += sep;-- if (sep === '/') {- // regexps may have modifiers /regexp/MOD , so fetch those, too- while (parser_pos < input_length && in_array(input.charAt(parser_pos), wordchar)) {- resulting_string += input.charAt(parser_pos);- parser_pos += 1;- }- }- return [resulting_string, 'TK_STRING'];- }-- if (c === '#') {--- if (output.length === 0 && input.charAt(parser_pos) === '!') {- // shebang- resulting_string = c;- while (parser_pos < input_length && c !== '\n') {- c = input.charAt(parser_pos);- resulting_string += c;- parser_pos += 1;- }- output.push(trim(resulting_string) + '\n');- print_newline();- return get_next_token();- }---- // Spidermonkey-specific sharp variables for circular references- // https://developer.mozilla.org/En/Sharp_variables_in_JavaScript- // http://mxr.mozilla.org/mozilla-central/source/js/src/jsscan.cpp around line 1935- var sharp = '#';- if (parser_pos < input_length && in_array(input.charAt(parser_pos), digits)) {- do {- c = input.charAt(parser_pos);- sharp += c;- parser_pos += 1;- } while (parser_pos < input_length && c !== '#' && c !== '=');- if (c === '#') {- //- } else if (input.charAt(parser_pos) === '[' && input.charAt(parser_pos + 1) === ']') {- sharp += '[]';- parser_pos += 2;- } else if (input.charAt(parser_pos) === '{' && input.charAt(parser_pos + 1) === '}') {- sharp += '{}';- parser_pos += 2;- }- return [sharp, 'TK_WORD'];- }- }-- if (c === '<' && input.substring(parser_pos - 1, parser_pos + 3) === '<!--') {- parser_pos += 3;- c = '<!--';- while (input.charAt(parser_pos) !== '\n' && parser_pos < input_length) {- c += input.charAt(parser_pos);- parser_pos++;- }- flags.in_html_comment = true;- return [c, 'TK_COMMENT'];- }-- if (c === '-' && flags.in_html_comment && input.substring(parser_pos - 1, parser_pos + 2) === '-->') {- flags.in_html_comment = false;- parser_pos += 2;- if (wanted_newline) {- print_newline();- }- return ['-->', 'TK_COMMENT'];- }-- if (in_array(c, punct)) {- while (parser_pos < input_length && in_array(c + input.charAt(parser_pos), punct)) {- c += input.charAt(parser_pos);- parser_pos += 1;- if (parser_pos >= input_length) {- break;- }- }-- if (c === ',') {- return [c, 'TK_COMMA'];- } else if (c === '=') {- return [c, 'TK_EQUALS'];- } else {- return [c, 'TK_OPERATOR'];- }- }-- return [c, 'TK_UNKNOWN'];- }-- //----------------------------------- indent_string = '';- while (opt_indent_size > 0) {- indent_string += opt_indent_char;- opt_indent_size -= 1;- }-- while (js_source_text && (js_source_text.charAt(0) === ' ' || js_source_text.charAt(0) === '\t')) {- preindent_string += js_source_text.charAt(0);- js_source_text = js_source_text.substring(1);- }- input = js_source_text;-- last_word = ''; // last 'TK_WORD' passed- last_type = 'TK_START_EXPR'; // last token type- last_text = ''; // last token text- last_last_text = ''; // pre-last token text- output = [];-- do_block_just_closed = false;-- whitespace = "\n\r\t ".split('');- wordchar = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$'.split('');- digits = '0123456789'.split('');-- punct = '+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> >>>= >>= <<= && &= | || ! !! , : ? ^ ^= |= ::';- punct += ' <%= <% %> <?= <? ?>'; // try to be a good boy and try not to break the markup language identifiers- punct = punct.split(' ');-- // words which should always start on new line.- line_starters = 'continue,try,throw,return,var,if,switch,case,default,for,while,break,function'.split(',');-- // states showing if we are currently in expression (i.e. "if" case) - 'EXPRESSION', or in usual block (like, procedure), 'BLOCK'.- // some formatting depends on that.- flag_store = [];- set_mode('BLOCK');-- parser_pos = 0;- while (true) {- var t = get_next_token(parser_pos);- token_text = t[0];- token_type = t[1];- if (token_type === 'TK_EOF') {- break;- }-- switch (token_type) {-- case 'TK_START_EXPR':-- if (token_text === '[') {-- if (last_type === 'TK_WORD' || last_text === ')') {- // this is array index specifier, break immediately- // a[x], fn()[x]- if (in_array(last_text, line_starters)) {- print_single_space();- }- set_mode('(EXPRESSION)');- print_token();- break;- }-- if (flags.mode === '[EXPRESSION]' || flags.mode === '[INDENTED-EXPRESSION]') {- if (last_last_text === ']' && last_text === ',') {- // ], [ goes to new line- if (flags.mode === '[EXPRESSION]') {- flags.mode = '[INDENTED-EXPRESSION]';- if (!opt_keep_array_indentation) {- indent();- }- }- set_mode('[EXPRESSION]');- if (!opt_keep_array_indentation) {- print_newline();- }- } else if (last_text === '[') {- if (flags.mode === '[EXPRESSION]') {- flags.mode = '[INDENTED-EXPRESSION]';- if (!opt_keep_array_indentation) {- indent();- }- }- set_mode('[EXPRESSION]');-- if (!opt_keep_array_indentation) {- print_newline();- }- } else {- set_mode('[EXPRESSION]');- }- } else {- set_mode('[EXPRESSION]');- }---- } else {- if (last_word === 'for') {- set_mode('(FOR-EXPRESSION)');- } else if (in_array(last_word, ['if', 'while'])) {- set_mode('(COND-EXPRESSION)');- } else {- set_mode('(EXPRESSION)');- }- }-- if (last_text === ';' || last_type === 'TK_START_BLOCK') {- print_newline();- } else if (last_type === 'TK_END_EXPR' || last_type === 'TK_START_EXPR' || last_type === 'TK_END_BLOCK' || last_text === '.') {- if (wanted_newline) {- print_newline();- }- // do nothing on (( and )( and ][ and ]( and .(- } else if (last_type !== 'TK_WORD' && last_type !== 'TK_OPERATOR') {- print_single_space();- } else if (last_word === 'function' || last_word === 'typeof') {- // function() vs function ()- if (opt_jslint_happy) {- print_single_space();- }- } else if (in_array(last_text, line_starters) || last_text === 'catch') {- if (opt_space_before_conditional) {- print_single_space();- }- }- print_token();-- break;-- case 'TK_END_EXPR':- if (token_text === ']') {- if (opt_keep_array_indentation) {- if (last_text === '}') {- // trim_output();- // print_newline(true);- remove_indent();- print_token();- restore_mode();- break;- }- } else {- if (flags.mode === '[INDENTED-EXPRESSION]') {- if (last_text === ']') {- restore_mode();- print_newline();- print_token();- break;- }- }- }- }- restore_mode();- print_token();- break;-- case 'TK_START_BLOCK':-- if (last_word === 'do') {- set_mode('DO_BLOCK');- } else {- set_mode('BLOCK');- }- if (opt_brace_style === "expand" || opt_brace_style === "expand-strict") {- var empty_braces = false;- if (opt_brace_style === "expand-strict") {- empty_braces = (look_up() === '}');- if (!empty_braces) {- print_newline(true);- }- } else {- if (last_type !== 'TK_OPERATOR') {- if (last_text === '=' || (is_special_word(last_text) && last_text !== 'else')) {- print_single_space();- } else {- print_newline(true);- }- }- }- print_token();- if (!empty_braces) {- indent();- }- } else {- if (last_type !== 'TK_OPERATOR' && last_type !== 'TK_START_EXPR') {- if (last_type === 'TK_START_BLOCK') {- print_newline();- } else {- print_single_space();- }- } else {- // if TK_OPERATOR or TK_START_EXPR- if (is_array(flags.previous_mode) && last_text === ',') {- if (last_last_text === '}') {- // }, { in array context- print_single_space();- } else {- print_newline(); // [a, b, c, {- }- }- }- indent();- print_token();- }-- break;-- case 'TK_END_BLOCK':- restore_mode();- if (opt_brace_style === "expand" || opt_brace_style === "expand-strict") {- if (last_text !== '{') {- print_newline();- }- print_token();- } else {- if (last_type === 'TK_START_BLOCK') {- // nothing- if (just_added_newline) {- remove_indent();- } else {- // {}- trim_output();- }- } else {- if (is_array(flags.mode) && opt_keep_array_indentation) {- // we REALLY need a newline here, but newliner would skip that- opt_keep_array_indentation = false;- print_newline();- opt_keep_array_indentation = true;-- } else {- print_newline();- }- }- print_token();- }- break;-- case 'TK_WORD':-- // no, it's not you. even I have problems understanding how this works- // and what does what.- if (do_block_just_closed) {- // do {} ## while ()- print_single_space();- print_token();- print_single_space();- do_block_just_closed = false;- break;- }-- prefix = 'NONE';-- if (token_text === 'function') {- if (flags.var_line && last_type !== 'TK_EQUALS' ) {- flags.var_line_reindented = true;- }- if ((just_added_newline || last_text === ';') && last_text !== '{'- && last_type !== 'TK_BLOCK_COMMENT' && last_type !== 'TK_COMMENT') {- // make sure there is a nice clean space of at least one blank line- // before a new function definition- n_newlines = just_added_newline ? n_newlines : 0;- if (!opt_preserve_newlines) {- n_newlines = 1;- }-- for (var i = 0; i < 2 - n_newlines; i++) {- print_newline(false);- }- }- if (last_type === 'TK_WORD') {- if (last_text === 'get' || last_text === 'set' || last_text === 'new' || last_text === 'return') {- print_single_space();- } else {- print_newline();- }- } else if (last_type === 'TK_OPERATOR' || last_text === '=') {- // foo = function- print_single_space();- } else if (is_expression(flags.mode)) {- // print nothing- } else {- print_newline();- }-- print_token();- last_word = token_text;- break;- }-- if (token_text === 'case' || (token_text === 'default' && flags.in_case_statement)) {- if (last_text === ':' || flags.case_body) {- // switch cases following one another- remove_indent();- } else {- // case statement starts in the same line where switch- if (!opt_indent_case) {- flags.indentation_level--;- }- print_newline();- if (!opt_indent_case) {- flags.indentation_level++;- }- }- print_token();- flags.in_case = true;- flags.in_case_statement = true;- flags.case_body = false;- break;- }-- if (last_type === 'TK_END_BLOCK') {-- if (!in_array(token_text.toLowerCase(), ['else', 'catch', 'finally'])) {- prefix = 'NEWLINE';- } else {- if (opt_brace_style === "expand" || opt_brace_style === "end-expand" || opt_brace_style === "expand-strict") {- prefix = 'NEWLINE';- } else {- prefix = 'SPACE';- print_single_space();- }- }- } else if (last_type === 'TK_SEMICOLON' && (flags.mode === 'BLOCK' || flags.mode === 'DO_BLOCK')) {- prefix = 'NEWLINE';- } else if (last_type === 'TK_SEMICOLON' && is_expression(flags.mode)) {- prefix = 'SPACE';- } else if (last_type === 'TK_STRING') {- prefix = 'NEWLINE';- } else if (last_type === 'TK_WORD') {- if (last_text === 'else') {- // eat newlines between ...else *** some_op...- // won't preserve extra newlines in this place (if any), but don't care that much- trim_output(true);- }- prefix = 'SPACE';- } else if (last_type === 'TK_START_BLOCK') {- prefix = 'NEWLINE';- } else if (last_type === 'TK_END_EXPR') {- print_single_space();- prefix = 'NEWLINE';- }-- if (in_array(token_text, line_starters) && last_text !== ')') {- if (last_text === 'else') {- prefix = 'SPACE';- } else {- prefix = 'NEWLINE';- }-- }-- if (flags.if_line && last_type === 'TK_END_EXPR') {- flags.if_line = false;- }- if (in_array(token_text.toLowerCase(), ['else', 'catch', 'finally'])) {- if (last_type !== 'TK_END_BLOCK' || opt_brace_style === "expand" || opt_brace_style === "end-expand" || opt_brace_style === "expand-strict") {- print_newline();- } else {- trim_output(true);- print_single_space();- }- } else if (prefix === 'NEWLINE') {- if (is_special_word(last_text)) {- // no newline between 'return nnn'- print_single_space();- } else if (last_type !== 'TK_END_EXPR') {- if ((last_type !== 'TK_START_EXPR' || token_text !== 'var') && last_text !== ':') {- // no need to force newline on 'var': for (var x = 0...)- if (token_text === 'if' && last_word === 'else' && last_text !== '{') {- // no newline for } else if {- print_single_space();- } else {- flags.var_line = false;- flags.var_line_reindented = false;- print_newline();- }- }- } else if (in_array(token_text, line_starters) && last_text !== ')') {- flags.var_line = false;- flags.var_line_reindented = false;- print_newline();- }- } else if (is_array(flags.mode) && last_text === ',' && last_last_text === '}') {- print_newline(); // }, in lists get a newline treatment- } else if (prefix === 'SPACE') {- print_single_space();- }- print_token();- last_word = token_text;-- if (token_text === 'var') {- flags.var_line = true;- flags.var_line_reindented = false;- flags.var_line_tainted = false;- }-- if (token_text === 'if') {- flags.if_line = true;- }- if (token_text === 'else') {- flags.if_line = false;- }-- break;-- case 'TK_SEMICOLON':-- print_token();- flags.var_line = false;- flags.var_line_reindented = false;- if (flags.mode === 'OBJECT') {- // OBJECT mode is weird and doesn't get reset too well.- flags.mode = 'BLOCK';- }- break;-- case 'TK_STRING':-- if (last_type === 'TK_END_EXPR' && in_array(flags.previous_mode, ['(COND-EXPRESSION)', '(FOR-EXPRESSION)'])) {- print_single_space();- } else if (last_type === 'TK_COMMENT' || last_type === 'TK_STRING' || last_type === 'TK_START_BLOCK' || last_type === 'TK_END_BLOCK' || last_type === 'TK_SEMICOLON') {- print_newline();- } else if (last_type === 'TK_WORD') {- print_single_space();- }- print_token();- break;-- case 'TK_EQUALS':- if (flags.var_line) {- // just got an '=' in a var-line, different formatting/line-breaking, etc will now be done- flags.var_line_tainted = true;- }- print_single_space();- print_token();- print_single_space();- break;-- case 'TK_COMMA':- if (flags.var_line) {- if (is_expression(flags.mode) || last_type === 'TK_END_BLOCK' ) {- // do not break on comma, for(var a = 1, b = 2)- flags.var_line_tainted = false;- }- if (flags.var_line_tainted) {- print_token();- flags.var_line_reindented = true;- flags.var_line_tainted = false;- print_newline();- break;- } else {- flags.var_line_tainted = false;- }-- print_token();- print_single_space();- break;- }-- if (last_type === 'TK_COMMENT') {- print_newline();- }-- if (last_type === 'TK_END_BLOCK' && flags.mode !== "(EXPRESSION)") {- print_token();- if (flags.mode === 'OBJECT' && last_text === '}') {- print_newline();- } else {- print_single_space();- }- } else {- if (flags.mode === 'OBJECT') {- print_token();- print_newline();- } else {- // EXPR or DO_BLOCK- print_token();- print_single_space();- }- }- break;--- case 'TK_OPERATOR':-- var space_before = true;- var space_after = true;-- if (is_special_word(last_text)) {- // "return" had a special handling in TK_WORD. Now we need to return the favor- print_single_space();- print_token();- break;- }-- // hack for actionscript's import .*;- if (token_text === '*' && last_type === 'TK_UNKNOWN' && !last_last_text.match(/^\d+$/)) {- print_token();- break;- }-- if (token_text === ':' && flags.in_case) {- if (opt_indent_case) {- flags.case_body = true;- }- print_token(); // colon really asks for separate treatment- print_newline();- flags.in_case = false;- break;- }-- if (token_text === '::') {- // no spaces around exotic namespacing syntax operator- print_token();- break;- }-- if (in_array(token_text, ['--', '++', '!']) || (in_array(token_text, ['-', '+']) && (in_array(last_type, ['TK_START_BLOCK', 'TK_START_EXPR', 'TK_EQUALS', 'TK_OPERATOR']) || in_array(last_text, line_starters)))) {- // unary operators (and binary +/- pretending to be unary) special cases-- space_before = false;- space_after = false;-- if (last_text === ';' && is_expression(flags.mode)) {- // for (;; ++i)- // ^^^- space_before = true;- }- if (last_type === 'TK_WORD' && in_array(last_text, line_starters)) {- space_before = true;- }-- if (flags.mode === 'BLOCK' && (last_text === '{' || last_text === ';')) {- // { foo; --i }- // foo(); --bar;- print_newline();- }- } else if (token_text === '.') {- // decimal digits or object.property- space_before = false;-- } else if (token_text === ':') {- if (flags.ternary_depth === 0) {- if (flags.mode === 'BLOCK') {- flags.mode = 'OBJECT';- }- space_before = false;- } else {- flags.ternary_depth -= 1;- }- } else if (token_text === '?') {- flags.ternary_depth += 1;- }- if (space_before) {- print_single_space();- }-- print_token();-- if (space_after) {- print_single_space();- }-- break;-- case 'TK_BLOCK_COMMENT':-- var lines = split_newlines(token_text);- var j; // iterator for this case-- if (all_lines_start_with(lines.slice(1), '*')) {- // javadoc: reformat and reindent- print_newline();- output.push(lines[0]);- for (j = 1; j < lines.length; j++) {- print_newline();- output.push(' ');- output.push(trim(lines[j]));- }-- } else {-- // simple block comment: leave intact- if (lines.length > 1) {- // multiline comment block starts with a new line- print_newline();- } else {- // single-line /* comment */ stays where it is- if (last_type === 'TK_END_BLOCK') {- print_newline();- } else {- print_single_space();- }-- }-- for (j = 0; j < lines.length; j++) {- output.push(lines[j]);- output.push("\n");- }-- }- if (look_up('\n') !== '\n') {- print_newline();- }- break;-- case 'TK_INLINE_COMMENT':- print_single_space();- print_token();- if (is_expression(flags.mode)) {- print_single_space();- } else {- force_newline();- }- break;-- case 'TK_COMMENT':-- if (last_text === ',' && !wanted_newline) {- trim_output(true);- }- if (last_type !== 'TK_COMMENT') {- if (wanted_newline) {- print_newline();- } else {- print_single_space();- }- }- print_token();- break;-- case 'TK_UNKNOWN':- if (is_special_word(last_text)) {- print_single_space();- }- print_token();- break;- }-- last_last_text = last_text;- last_type = token_type;- last_text = token_text;- }-- var sweet_code = preindent_string + output.join('').replace(/[\r\n ]+$/, '');- return sweet_code;--}--// Add support for CommonJS. Just put this file somewhere on your require.paths-// and you will be able to `var js_beautify = require("beautify").js_beautify`.-if (typeof exports !== "undefined") {- exports.js_beautify = js_beautify;-}
− docs/highlight.pack.js
@@ -1,1 +0,0 @@-var hljs=new function(){function l(o){return o.replace(/&/gm,"&").replace(/</gm,"<")}function c(q,p,o){return RegExp(p,"m"+(q.cI?"i":"")+(o?"g":""))}function i(q){for(var o=0;o<q.childNodes.length;o++){var p=q.childNodes[o];if(p.nodeName=="CODE"){return p}if(!(p.nodeType==3&&p.nodeValue.match(/\s+/))){break}}}function g(s,r){var q="";for(var p=0;p<s.childNodes.length;p++){if(s.childNodes[p].nodeType==3){var o=s.childNodes[p].nodeValue;if(r){o=o.replace(/\n/g,"")}q+=o}else{if(s.childNodes[p].nodeName=="BR"){q+="\n"}else{q+=g(s.childNodes[p])}}}if(/MSIE [678]/.test(navigator.userAgent)){q=q.replace(/\r/g,"\n")}return q}function a(r){var p=r.className.split(/\s+/);p=p.concat(r.parentNode.className.split(/\s+/));for(var o=0;o<p.length;o++){var q=p[o].replace(/^language-/,"");if(d[q]||q=="no-highlight"){return q}}}function b(o){var p=[];(function(r,s){for(var q=0;q<r.childNodes.length;q++){if(r.childNodes[q].nodeType==3){s+=r.childNodes[q].nodeValue.length}else{if(r.childNodes[q].nodeName=="BR"){s+=1}else{p.push({event:"start",offset:s,node:r.childNodes[q]});s=arguments.callee(r.childNodes[q],s);p.push({event:"stop",offset:s,node:r.childNodes[q]})}}}return s})(o,0);return p}function k(x,y,w){var q=0;var v="";var s=[];function t(){if(x.length&&y.length){if(x[0].offset!=y[0].offset){return(x[0].offset<y[0].offset)?x:y}else{return y[0].event=="start"?x:y}}else{return x.length?x:y}}function r(B){var C="<"+B.nodeName.toLowerCase();for(var z=0;z<B.attributes.length;z++){var A=B.attributes[z];C+=" "+A.nodeName.toLowerCase();if(A.nodeValue!=undefined){C+='="'+l(A.nodeValue)+'"'}}return C+">"}while(x.length||y.length){var u=t().splice(0,1)[0];v+=l(w.substr(q,u.offset-q));q=u.offset;if(u.event=="start"){v+=r(u.node);s.push(u.node)}else{if(u.event=="stop"){var p=s.length;do{p--;var o=s[p];v+=("</"+o.nodeName.toLowerCase()+">")}while(o!=u.node);s.splice(p,1);while(p<s.length){v+=r(s[p]);p++}}}}v+=w.substr(q);return v}function f(I,C){function y(r,L){for(var K=0;K<L.c.length;K++){if(L.c[K].bR.test(r)){return L.c[K]}}}function v(K,r){if(B[K].e&&B[K].eR.test(r)){return 1}if(B[K].eW){var L=v(K-1,r);return L?L+1:0}return 0}function w(r,K){return K.iR&&K.iR.test(r)}function z(N,M){var L=[];for(var K=0;K<N.c.length;K++){L.push(N.c[K].b)}var r=B.length-1;do{if(B[r].e){L.push(B[r].e)}r--}while(B[r+1].eW);if(N.i){L.push(N.i)}return c(M,"("+L.join("|")+")",true)}function q(L,K){var M=B[B.length-1];if(!M.t){M.t=z(M,G)}M.t.lastIndex=K;var r=M.t.exec(L);if(r){return[L.substr(K,r.index-K),r[0],false]}else{return[L.substr(K),"",true]}}function o(N,r){var K=G.cI?r[0].toLowerCase():r[0];for(var M in N.kG){if(!N.kG.hasOwnProperty(M)){continue}var L=N.kG[M].hasOwnProperty(K);if(L){return[M,L]}}return false}function E(L,N){if(!N.k){return l(L)}var M="";var O=0;N.lR.lastIndex=0;var K=N.lR.exec(L);while(K){M+=l(L.substr(O,K.index-O));var r=o(N,K);if(r){s+=r[1];M+='<span class="'+r[0]+'">'+l(K[0])+"</span>"}else{M+=l(K[0])}O=N.lR.lastIndex;K=N.lR.exec(L)}M+=l(L.substr(O,L.length-O));return M}function J(r,L){if(L.sL&&d[L.sL]){var K=f(L.sL,r);s+=K.keyword_count;return K.value}else{return E(r,L)}}function H(L,r){var K=L.cN?'<span class="'+L.cN+'">':"";if(L.rB){p+=K;L.buffer=""}else{if(L.eB){p+=l(r)+K;L.buffer=""}else{p+=K;L.buffer=r}}B.push(L);A+=L.r}function D(N,K,P){var Q=B[B.length-1];if(P){p+=J(Q.buffer+N,Q);return false}var L=y(K,Q);if(L){p+=J(Q.buffer+N,Q);H(L,K);return L.rB}var r=v(B.length-1,K);if(r){var M=Q.cN?"</span>":"";if(Q.rE){p+=J(Q.buffer+N,Q)+M}else{if(Q.eE){p+=J(Q.buffer+N,Q)+M+l(K)}else{p+=J(Q.buffer+N+K,Q)+M}}while(r>1){M=B[B.length-2].cN?"</span>":"";p+=M;r--;B.length--}var O=B[B.length-1];B.length--;B[B.length-1].buffer="";if(O.starts){H(O.starts,"")}return Q.rE}if(w(K,Q)){throw"Illegal"}}var G=d[I];var B=[G.dM];var A=0;var s=0;var p="";try{var u=0;G.dM.buffer="";do{var x=q(C,u);var t=D(x[0],x[1],x[2]);u+=x[0].length;if(!t){u+=x[1].length}}while(!x[2]);if(B.length>1){throw"Illegal"}return{language:I,r:A,keyword_count:s,value:p}}catch(F){if(F=="Illegal"){return{language:null,r:0,keyword_count:0,value:l(C)}}else{throw F}}}function h(){function o(t,s,u){if(t.compiled){return}if(!u){t.bR=c(s,t.b?t.b:"\\B|\\b");if(!t.e&&!t.eW){t.e="\\B|\\b"}if(t.e){t.eR=c(s,t.e)}}if(t.i){t.iR=c(s,t.i)}if(t.r==undefined){t.r=1}if(t.k){t.lR=c(s,t.l||hljs.IR,true)}for(var r in t.k){if(!t.k.hasOwnProperty(r)){continue}if(t.k[r] instanceof Object){t.kG=t.k}else{t.kG={keyword:t.k}}break}if(!t.c){t.c=[]}t.compiled=true;for(var q=0;q<t.c.length;q++){o(t.c[q],s,false)}if(t.starts){o(t.starts,s,false)}}for(var p in d){if(!d.hasOwnProperty(p)){continue}o(d[p].dM,d[p],true)}}function e(){if(e.called){return}e.called=true;h()}function n(t,y,p){e();var A=g(t,p);var r=a(t);if(r=="no-highlight"){return}if(r){var w=f(r,A)}else{var w={language:"",keyword_count:0,r:0,value:l(A)};var x=w;for(var z in d){if(!d.hasOwnProperty(z)){continue}var u=f(z,A);if(u.keyword_count+u.r>x.keyword_count+x.r){x=u}if(u.keyword_count+u.r>w.keyword_count+w.r){x=w;w=u}}}var s=t.className;if(!s.match(w.language)){s=s?(s+" "+w.language):w.language}var o=b(t);if(o.length){var q=document.createElement("pre");q.innerHTML=w.value;w.value=k(o,b(q),A)}if(y){w.value=w.value.replace(/^((<[^>]+>|\t)+)/gm,function(B,E,D,C){return E.replace(/\t/g,y)})}if(p){w.value=w.value.replace(/\n/g,"<br>")}if(/MSIE [678]/.test(navigator.userAgent)&&t.tagName=="CODE"&&t.parentNode.tagName=="PRE"){var q=t.parentNode;var v=document.createElement("div");v.innerHTML="<pre><code>"+w.value+"</code></pre>";t=v.firstChild.firstChild;v.firstChild.cN=q.cN;q.parentNode.replaceChild(v.firstChild,q)}else{t.innerHTML=w.value}t.className=s;t.dataset={};t.dataset.result={language:w.language,kw:w.keyword_count,re:w.r};if(x&&x.language){t.dataset.second_best={language:x.language,kw:x.keyword_count,re:x.r}}}function j(){if(j.called){return}j.called=true;e();var q=document.getElementsByTagName("pre");for(var o=0;o<q.length;o++){var p=i(q[o]);if(p){n(p,hljs.tabReplace)}}}function m(){var o=arguments;var p=function(){j.apply(null,o)};if(window.addEventListener){window.addEventListener("DOMContentLoaded",p,false);window.addEventListener("load",p,false)}else{if(window.attachEvent){window.attachEvent("onload",p)}else{window.onload=p}}}var d={};this.LANGUAGES=d;this.initHighlightingOnLoad=m;this.highlightBlock=n;this.initHighlighting=j;this.IR="[a-zA-Z][a-zA-Z0-9_]*";this.UIR="[a-zA-Z_][a-zA-Z0-9_]*";this.NR="\\b\\d+(\\.\\d+)?";this.CNR="\\b(0x[A-Za-z0-9]+|\\d+(\\.\\d+)?)";this.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|\\.|-|-=|/|/=|:|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~";this.BE={b:"\\\\.",r:0};this.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[this.BE],r:0};this.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[this.BE],r:0};this.CLCM={cN:"comment",b:"//",e:"$"};this.CBLCLM={cN:"comment",b:"/\\*",e:"\\*/"};this.HCM={cN:"comment",b:"#",e:"$"};this.NM={cN:"number",b:this.NR,r:0};this.CNM={cN:"number",b:this.CNR,r:0};this.inherit=function(o,r){var q={};for(var p in o){q[p]=o[p]}if(r){for(var p in r){q[p]=r[p]}}return q}}();hljs.LANGUAGES.bash=function(){var d={"true":1,"false":1};var b={cN:"variable",b:"\\$([a-zA-Z0-9_]+)\\b"};var a={cN:"variable",b:"\\$\\{(([^}])|(\\\\}))+\\}",c:[hljs.CNM]};var c={cN:"string",b:'"',e:'"',i:"\\n",c:[hljs.BE,b,a],r:0};var e={cN:"test_condition",b:"",e:"",c:[c,b,a,hljs.CNM],k:{literal:d},r:0};return{dM:{k:{keyword:{"if":1,then:1,"else":1,fi:1,"for":1,"break":1,"continue":1,"while":1,"in":1,"do":1,done:1,echo:1,exit:1,"return":1,set:1,declare:1},literal:d},c:[{cN:"shebang",b:"(#!\\/bin\\/bash)|(#!\\/bin\\/sh)",r:10},hljs.HCM,{cN:"comment",b:"\\/\\/",e:"$",i:"."},hljs.CNM,c,b,a,hljs.inherit(e,{b:"\\[ ",e:" \\]",r:0}),hljs.inherit(e,{b:"\\[\\[ ",e:" \\]\\]"})]}}}();hljs.LANGUAGES.erlang=function(){var g="[a-z'][a-zA-Z0-9_']*";var l="("+g+":"+g+"|"+g+")";var d={keyword:{after:1,and:1,andalso:10,band:1,begin:1,bnot:1,bor:1,bsl:1,bzr:1,bxor:1,"case":1,"catch":1,cond:1,div:1,end:1,fun:1,let:1,not:1,of:1,orelse:10,query:1,receive:1,rem:1,"try":1,when:1,xor:1},literal:{"false":1,"true":1}};var j={cN:"comment",b:"%",e:"$",r:0};var c={b:"fun\\s+"+g+"/\\d+"};var m={b:l+"\\(",e:"\\)",rB:true,r:0,c:[{cN:"function_name",b:l,r:0},{b:"\\(",e:"\\)",eW:true,rE:true,r:0}]};var f={cN:"tuple",b:"{",e:"}",r:0};var a={cN:"variable",b:"\\b_([A-Z][A-Za-z0-9_]*)?",r:0};var k={cN:"variable",b:"[A-Z][a-zA-Z0-9_]*",r:0};var h={b:"#",e:"}",i:".",r:0,rB:true,c:[{cN:"record_name",b:"#"+hljs.UIR,r:0},{b:"{",eW:true,r:0}]};var i={k:d,b:"(fun|receive|if|try|case)",e:"end"};i.c=[j,c,hljs.inherit(hljs.ASM,{cN:""}),i,m,hljs.QSM,hljs.CNM,f,a,k,h];var b=[j,c,i,m,hljs.QSM,hljs.CNM,f,a,k,h];m.c[1].c=b;f.c=b;h.c[1].c=b;var e={cN:"params",b:"\\(",e:"\\)",eW:true,c:b};return{dM:{k:d,i:"(</|\\*=|\\+=|-=|/=|/\\*|\\*/|\\(\\*|\\*\\))",c:[{cN:"function",b:"^"+g+"\\(",e:";|\\.",rB:true,c:[e,{cN:"title",b:g},{k:d,b:"->",eW:true,c:b}]},j,{cN:"pp",b:"^-",e:"\\.",r:0,eE:true,rB:true,l:"-"+hljs.IR,k:{"-module":1,"-record":1,"-undef":1,"-export":1,"-ifdef":1,"-ifndef":1,"-author":1,"-copyright":1,"-doc":1,"-vsn":1,"-import":1,"-include":1,"-include_lib":1,"-compile":1,"-define":1,"-else":1,"-endif":1,"-file":1,"-behaviour":1,"-behavior":1},c:[e]},hljs.CNM,hljs.QSM,h,a,k,f]}}}();hljs.LANGUAGES.cs={dM:{k:{"abstract":1,as:1,base:1,bool:1,"break":1,"byte":1,"case":1,"catch":1,"char":1,checked:1,"class":1,"const":1,"continue":1,decimal:1,"default":1,delegate:1,"do":1,"do":1,"double":1,"else":1,"enum":1,event:1,explicit:1,extern:1,"false":1,"finally":1,fixed:1,"float":1,"for":1,foreach:1,"goto":1,"if":1,implicit:1,"in":1,"int":1,"interface":1,internal:1,is:1,lock:1,"long":1,namespace:1,"new":1,"null":1,object:1,operator:1,out:1,override:1,params:1,"private":1,"protected":1,"public":1,readonly:1,ref:1,"return":1,sbyte:1,sealed:1,"short":1,sizeof:1,stackalloc:1,"static":1,string:1,struct:1,"switch":1,"this":1,"throw":1,"true":1,"try":1,"typeof":1,uint:1,ulong:1,unchecked:1,unsafe:1,ushort:1,using:1,virtual:1,"volatile":1,"void":1,"while":1,ascending:1,descending:1,from:1,get:1,group:1,into:1,join:1,let:1,orderby:1,partial:1,select:1,set:1,value:1,"var":1,where:1,yield:1},c:[{cN:"comment",b:"///",e:"$",rB:true,c:[{cN:"xmlDocTag",b:"///|<!--|-->"},{cN:"xmlDocTag",b:"</?",e:">"}]},hljs.CLCM,hljs.CBLCLM,{cN:"string",b:'@"',e:'"',c:[{b:'""'}]},hljs.ASM,hljs.QSM,hljs.CNM]}};hljs.LANGUAGES.ruby=function(){var g="[a-zA-Z_][a-zA-Z0-9_]*(\\!|\\?)?";var a="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?";var n={keyword:{and:1,"false":1,then:1,defined:1,module:1,"in":1,"return":1,redo:1,"if":1,BEGIN:1,retry:1,end:1,"for":1,"true":1,self:1,when:1,next:1,until:1,"do":1,begin:1,unless:1,END:1,rescue:1,nil:1,"else":1,"break":1,undef:1,not:1,"super":1,"class":1,"case":1,require:1,yield:1,alias:1,"while":1,ensure:1,elsif:1,or:1,def:1},keymethods:{__id__:1,__send__:1,abort:1,abs:1,"all?":1,allocate:1,ancestors:1,"any?":1,arity:1,assoc:1,at:1,at_exit:1,autoload:1,"autoload?":1,"between?":1,binding:1,binmode:1,"block_given?":1,call:1,callcc:1,caller:1,capitalize:1,"capitalize!":1,casecmp:1,"catch":1,ceil:1,center:1,chomp:1,"chomp!":1,chop:1,"chop!":1,chr:1,"class":1,class_eval:1,"class_variable_defined?":1,class_variables:1,clear:1,clone:1,close:1,close_read:1,close_write:1,"closed?":1,coerce:1,collect:1,"collect!":1,compact:1,"compact!":1,concat:1,"const_defined?":1,const_get:1,const_missing:1,const_set:1,constants:1,count:1,crypt:1,"default":1,default_proc:1,"delete":1,"delete!":1,delete_at:1,delete_if:1,detect:1,display:1,div:1,divmod:1,downcase:1,"downcase!":1,downto:1,dump:1,dup:1,each:1,each_byte:1,each_index:1,each_key:1,each_line:1,each_pair:1,each_value:1,each_with_index:1,"empty?":1,entries:1,eof:1,"eof?":1,"eql?":1,"equal?":1,"eval":1,exec:1,exit:1,"exit!":1,extend:1,fail:1,fcntl:1,fetch:1,fileno:1,fill:1,find:1,find_all:1,first:1,flatten:1,"flatten!":1,floor:1,flush:1,for_fd:1,foreach:1,fork:1,format:1,freeze:1,"frozen?":1,fsync:1,getc:1,gets:1,global_variables:1,grep:1,gsub:1,"gsub!":1,"has_key?":1,"has_value?":1,hash:1,hex:1,id:1,include:1,"include?":1,included_modules:1,index:1,indexes:1,indices:1,induced_from:1,inject:1,insert:1,inspect:1,instance_eval:1,instance_method:1,instance_methods:1,"instance_of?":1,"instance_variable_defined?":1,instance_variable_get:1,instance_variable_set:1,instance_variables:1,"integer?":1,intern:1,invert:1,ioctl:1,"is_a?":1,isatty:1,"iterator?":1,join:1,"key?":1,keys:1,"kind_of?":1,lambda:1,last:1,length:1,lineno:1,ljust:1,load:1,local_variables:1,loop:1,lstrip:1,"lstrip!":1,map:1,"map!":1,match:1,max:1,"member?":1,merge:1,"merge!":1,method:1,"method_defined?":1,method_missing:1,methods:1,min:1,module_eval:1,modulo:1,name:1,nesting:1,"new":1,next:1,"next!":1,"nil?":1,nitems:1,"nonzero?":1,object_id:1,oct:1,open:1,pack:1,partition:1,pid:1,pipe:1,pop:1,popen:1,pos:1,prec:1,prec_f:1,prec_i:1,print:1,printf:1,private_class_method:1,private_instance_methods:1,"private_method_defined?":1,private_methods:1,proc:1,protected_instance_methods:1,"protected_method_defined?":1,protected_methods:1,public_class_method:1,public_instance_methods:1,"public_method_defined?":1,public_methods:1,push:1,putc:1,puts:1,quo:1,raise:1,rand:1,rassoc:1,read:1,read_nonblock:1,readchar:1,readline:1,readlines:1,readpartial:1,rehash:1,reject:1,"reject!":1,remainder:1,reopen:1,replace:1,require:1,"respond_to?":1,reverse:1,"reverse!":1,reverse_each:1,rewind:1,rindex:1,rjust:1,round:1,rstrip:1,"rstrip!":1,scan:1,seek:1,select:1,send:1,set_trace_func:1,shift:1,singleton_method_added:1,singleton_methods:1,size:1,sleep:1,slice:1,"slice!":1,sort:1,"sort!":1,sort_by:1,split:1,sprintf:1,squeeze:1,"squeeze!":1,srand:1,stat:1,step:1,store:1,strip:1,"strip!":1,sub:1,"sub!":1,succ:1,"succ!":1,sum:1,superclass:1,swapcase:1,"swapcase!":1,sync:1,syscall:1,sysopen:1,sysread:1,sysseek:1,system:1,syswrite:1,taint:1,"tainted?":1,tell:1,test:1,"throw":1,times:1,to_a:1,to_ary:1,to_f:1,to_hash:1,to_i:1,to_int:1,to_io:1,to_proc:1,to_s:1,to_str:1,to_sym:1,tr:1,"tr!":1,tr_s:1,"tr_s!":1,trace_var:1,transpose:1,trap:1,truncate:1,"tty?":1,type:1,ungetc:1,uniq:1,"uniq!":1,unpack:1,unshift:1,untaint:1,untrace_var:1,upcase:1,"upcase!":1,update:1,upto:1,"value?":1,values:1,values_at:1,warn:1,write:1,write_nonblock:1,"zero?":1,zip:1}};var h={cN:"yardoctag",b:"@[A-Za-z]+"};var d={cN:"comment",b:"#",e:"$",c:[h]};var c={cN:"comment",b:"^\\=begin",e:"^\\=end",c:[h],r:10};var b={cN:"comment",b:"^__END__",e:"\\n$"};var u={cN:"subst",b:"#\\{",e:"}",l:g,k:n};var p=[hljs.BE,u];var s={cN:"string",b:"'",e:"'",c:p,r:0};var r={cN:"string",b:'"',e:'"',c:p,r:0};var q={cN:"string",b:"%[qw]?\\(",e:"\\)",c:p,r:10};var o={cN:"string",b:"%[qw]?\\[",e:"\\]",c:p,r:10};var m={cN:"string",b:"%[qw]?{",e:"}",c:p,r:10};var l={cN:"string",b:"%[qw]?<",e:">",c:p,r:10};var k={cN:"string",b:"%[qw]?/",e:"/",c:p,r:10};var j={cN:"string",b:"%[qw]?%",e:"%",c:p,r:10};var i={cN:"string",b:"%[qw]?-",e:"-",c:p,r:10};var t={cN:"string",b:"%[qw]?\\|",e:"\\|",c:p,r:10};var e={cN:"function",b:"\\bdef\\s+",e:" |$|;",l:g,k:n,c:[{cN:"title",b:a,l:g,k:n},{cN:"params",b:"\\(",e:"\\)",l:g,k:n},d,c,b]};var f={cN:"identifier",b:g,l:g,k:n,r:0};var v=[d,c,b,s,r,q,o,m,l,k,j,i,t,{cN:"class",b:"\\b(class|module)\\b",e:"$|;",k:{"class":1,module:1},c:[{cN:"title",b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?",r:0},{cN:"inheritance",b:"<\\s*",c:[{cN:"parent",b:"("+hljs.IR+"::)?"+hljs.IR}]},d,c,b]},e,{cN:"constant",b:"(::)?([A-Z]\\w*(::)?)+",r:0},{cN:"symbol",b:":",c:[s,r,q,o,m,l,k,j,i,t,f],r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{cN:"number",b:"\\?\\w"},{cN:"variable",b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},f,{b:"("+hljs.RSR+")\\s*",c:[d,c,b,{cN:"regexp",b:"/",e:"/[a-z]*",i:"\\n",c:[hljs.BE]}],r:0}];u.c=v;e.c[1].c=v;return{dM:{l:g,k:n,c:v}}}();hljs.LANGUAGES.diff={cI:true,dM:{c:[{cN:"chunk",b:"^\\@\\@ +\\-\\d+,\\d+ +\\+\\d+,\\d+ +\\@\\@$",r:10},{cN:"chunk",b:"^\\*\\*\\* +\\d+,\\d+ +\\*\\*\\*\\*$",r:10},{cN:"chunk",b:"^\\-\\-\\- +\\d+,\\d+ +\\-\\-\\-\\-$",r:10},{cN:"header",b:"Index: ",e:"$"},{cN:"header",b:"=====",e:"=====$"},{cN:"header",b:"^\\-\\-\\-",e:"$"},{cN:"header",b:"^\\*{3} ",e:"$"},{cN:"header",b:"^\\+\\+\\+",e:"$"},{cN:"header",b:"\\*{5}",e:"\\*{5}$"},{cN:"addition",b:"^\\+",e:"$"},{cN:"deletion",b:"^\\-",e:"$"},{cN:"change",b:"^\\!",e:"$"}]}};hljs.LANGUAGES.javascript={dM:{k:{keyword:{"in":1,"if":1,"for":1,"while":1,"finally":1,"var":1,"new":1,"function":1,"do":1,"return":1,"void":1,"else":1,"break":1,"catch":1,"instanceof":1,"with":1,"throw":1,"case":1,"default":1,"try":1,"this":1,"switch":1,"continue":1,"typeof":1,"delete":1},literal:{"true":1,"false":1,"null":1}},c:[hljs.ASM,hljs.QSM,hljs.CLCM,hljs.CBLCLM,hljs.CNM,{b:"("+hljs.RSR+"|case|return|throw)\\s*",k:{"return":1,"throw":1,"case":1},c:[hljs.CLCM,hljs.CBLCLM,{cN:"regexp",b:"/.*?[^\\\\/]/[gim]*"}],r:0},{cN:"function",b:"\\bfunction\\b",e:"{",k:{"function":1},c:[{cN:"title",b:"[A-Za-z$_][0-9A-Za-z$_]*"},{cN:"params",b:"\\(",e:"\\)",c:[hljs.ASM,hljs.QSM,hljs.CLCM,hljs.CBLCLM]}]}]}};hljs.LANGUAGES.lua=function(){var b="\\[=*\\[";var e="\\]=*\\]";var a={b:b,e:e};a.c=[a];var d={cN:"comment",b:"--(?!"+b+")",e:"$"};var c={cN:"comment",b:"--"+b,e:e,c:[a],r:10};return{dM:{l:hljs.UIR,k:{keyword:{and:1,"break":1,"do":1,"else":1,elseif:1,end:1,"false":1,"for":1,"if":1,"in":1,local:1,nil:1,not:1,or:1,repeat:1,"return":1,then:1,"true":1,until:1,"while":1},built_in:{_G:1,_VERSION:1,assert:1,collectgarbage:1,dofile:1,error:1,getfenv:1,getmetatable:1,ipairs:1,load:1,loadfile:1,loadstring:1,module:1,next:1,pairs:1,pcall:1,print:1,rawequal:1,rawget:1,rawset:1,require:1,select:1,setfenv:1,setmetatable:1,tonumber:1,tostring:1,type:1,unpack:1,xpcall:1,coroutine:1,debug:1,io:1,math:1,os:1,"package":1,string:1,table:1}},c:[d,c,{cN:"function",b:"\\bfunction\\b",e:"\\)",k:{"function":1},c:[{cN:"title",b:"([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*"},{cN:"params",b:"\\(",eW:true,c:[d,c]},d,c]},hljs.CNM,hljs.ASM,hljs.QSM,{cN:"string",b:b,e:e,c:[a],r:10}]}}}();hljs.LANGUAGES.css=function(){var a={cN:"function",b:hljs.IR+"\\(",e:"\\)",c:[{eW:true,eE:true,c:[hljs.NM,hljs.ASM,hljs.QSM]}]};return{cI:true,dM:{i:"[=/|']",c:[hljs.CBLCLM,{cN:"id",b:"\\#[A-Za-z0-9_-]+"},{cN:"class",b:"\\.[A-Za-z0-9_-]+",r:0},{cN:"attr_selector",b:"\\[",e:"\\]",i:"$"},{cN:"pseudo",b:":(:)?[a-zA-Z0-9\\_\\-\\+\\(\\)\\\"\\']+"},{cN:"at_rule",b:"@font-face",l:"[a-z-]+",k:{"font-face":1}},{cN:"at_rule",b:"@",e:"[{;]",eE:true,k:{"import":1,page:1,media:1,charset:1},c:[a,hljs.ASM,hljs.QSM,hljs.NM]},{cN:"tag",b:hljs.IR,r:0},{cN:"rules",b:"{",e:"}",i:"[^\\s]",r:0,c:[hljs.CBLCLM,{cN:"rule",b:"[^\\s]",rB:true,e:";",eW:true,c:[{cN:"attribute",b:"[A-Z\\_\\.\\-]+",e:":",eE:true,i:"[^\\s]",starts:{cN:"value",eW:true,eE:true,c:[a,hljs.NM,hljs.QSM,hljs.ASM,hljs.CBLCLM,{cN:"hexcolor",b:"\\#[0-9A-F]+"},{cN:"important",b:"!important"}]}}]}]}]}}}();hljs.LANGUAGES.xml=function(){var b="[A-Za-z0-9\\._:-]+";var a={eW:true,c:[{cN:"attribute",b:b,r:0},{b:'="',rB:true,e:'"',c:[{cN:"value",b:'"',eW:true}]},{b:"='",rB:true,e:"'",c:[{cN:"value",b:"'",eW:true}]},{b:"=",c:[{cN:"value",b:"[^\\s/>]+"}]}]};return{cI:true,dM:{c:[{cN:"pi",b:"<\\?",e:"\\?>",r:10},{cN:"doctype",b:"<!DOCTYPE",e:">",r:10},{cN:"comment",b:"<!--",e:"-->",r:10},{cN:"cdata",b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{cN:"tag",b:"<style",e:">",k:{title:{style:1}},c:[a],starts:{cN:"css",e:"</style>",rE:true,sL:"css"}},{cN:"tag",b:"<script",e:">",k:{title:{script:1}},c:[a],starts:{cN:"javascript",e:"<\/script>",rE:true,sL:"javascript"}},{cN:"vbscript",b:"<%",e:"%>",sL:"vbscript"},{cN:"tag",b:"</?",e:"/?>",c:[{cN:"title",b:"[^ />]+"},a]}]}}}();hljs.LANGUAGES.lisp=function(){var m="[a-zA-Z_\\-\\+\\*\\/\\<\\=\\>\\&\\#][a-zA-Z0-9_\\-\\+\\*\\/\\<\\=\\>\\&\\#]*";var n="(\\-|\\+)?\\d+(\\.\\d+|\\/\\d+)?((d|e|f|l|s)(\\+|\\-)?\\d+)?";var c={cN:"literal",b:"\\b(t{1}|nil)\\b"};var o={cN:"number",b:n};var p={cN:"number",b:"#b[0-1]+(/[0-1]+)?"};var q={cN:"number",b:"#o[0-7]+(/[0-7]+)?"};var a={cN:"number",b:"#x[0-9a-f]+(/[0-9a-f]+)?"};var b={cN:"number",b:"#c\\("+n+" +"+n,e:"\\)"};var e={cN:"string",b:'"',e:'"',c:[hljs.BE],r:0};var l={cN:"comment",b:";",e:"$"};var d={cN:"variable",b:"\\*",e:"\\*"};var k={cN:"keyword",b:"[:&]"+m};var i={b:"\\(",e:"\\)"};i.c=[i,c,o,p,q,a,b,e];var g={cN:"quoted",b:"['`]\\(",e:"\\)",c:[o,p,q,a,b,e,d,k,i]};var f={cN:"quoted",b:"\\(quote ",e:"\\)",k:{title:{quote:1}},c:[o,p,q,a,b,e,d,k,i]};var j={cN:"list",b:"\\(",e:"\\)"};var h={cN:"body",eW:true,eE:true};j.c=[{cN:"title",b:m},h];h.c=[g,f,j,c,o,p,q,a,b,e,l,d,k];return{cI:true,dM:{i:"[^\\s]",c:[c,o,p,q,a,b,e,l,g,f,j]}}}();hljs.LANGUAGES.java={dM:{k:{"false":1,"synchronized":1,"int":1,"abstract":1,"float":1,"private":1,"char":1,"interface":1,"boolean":1,"static":1,"null":1,"if":1,"const":1,"for":1,"true":1,"while":1,"long":1,"throw":1,strictfp:1,"finally":1,"protected":1,"extends":1,"import":1,"native":1,"final":1,"implements":1,"return":1,"void":1,"enum":1,"else":1,"break":1,"transient":1,"new":1,"catch":1,"instanceof":1,"byte":1,"super":1,"class":1,"volatile":1,"case":1,assert:1,"short":1,"package":1,"default":1,"double":1,"public":1,"try":1,"this":1,"switch":1,"continue":1,"throws":1},c:[{cN:"javadoc",b:"/\\*\\*",e:"\\*/",c:[{cN:"javadoctag",b:"@[A-Za-z]+"}],r:10},hljs.CLCM,hljs.CBLCLM,hljs.ASM,hljs.QSM,{cN:"class",b:"(class |interface )",e:"{",k:{"class":1,"interface":1},i:":",c:[{b:"(implements|extends)",k:{"extends":1,"implements":1},r:10},{cN:"title",b:hljs.UIR}]},hljs.CNM,{cN:"annotation",b:"@[A-Za-z]+"}]}};hljs.LANGUAGES.php={cI:true,dM:{k:{and:1,include_once:1,list:1,"abstract":1,global:1,"private":1,echo:1,"interface":1,as:1,"static":1,endswitch:1,array:1,"null":1,"if":1,endwhile:1,or:1,"const":1,"for":1,endforeach:1,self:1,"var":1,"while":1,isset:1,"public":1,"protected":1,exit:1,foreach:1,"throw":1,elseif:1,"extends":1,include:1,__FILE__:1,empty:1,require_once:1,"function":1,"do":1,xor:1,"return":1,"implements":1,parent:1,clone:1,use:1,__CLASS__:1,__LINE__:1,"else":1,"break":1,print:1,"eval":1,"new":1,"catch":1,__METHOD__:1,"class":1,"case":1,exception:1,php_user_filter:1,"default":1,die:1,require:1,__FUNCTION__:1,enddeclare:1,"final":1,"try":1,"this":1,"switch":1,"continue":1,endfor:1,endif:1,declare:1,unset:1,"true":1,"false":1,namespace:1},c:[hljs.CLCM,hljs.HCM,{cN:"comment",b:"/\\*",e:"\\*/",c:[{cN:"phpdoc",b:"\\s@[A-Za-z]+",r:10}]},hljs.CNM,hljs.inherit(hljs.ASM,{i:null}),hljs.inherit(hljs.QSM,{i:null}),{cN:"variable",b:"\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*"},{cN:"preprocessor",b:"<\\?php",r:10},{cN:"preprocessor",b:"\\?>"}]}};hljs.LANGUAGES.haskell=function(){var a={cN:"label",b:"\\b[A-Z][\\w\\']*",r:0};var b={cN:"container",b:"\\(",e:"\\)",c:[{cN:"label",b:"\\b[A-Z][\\w\\(\\)\\.\\']*"},{cN:"title",b:"[_a-z][\\w\\']*"}]};return{dM:{k:{keyword:{let:1,"in":1,"if":1,then:1,"else":1,"case":1,of:1,where:1,"do":1,module:1,"import":1,hiding:1,qualified:1,type:1,data:1,newtype:1,deriving:1,"class":1,instance:1,"null":1,not:1,as:1},built_in:{Bool:1,True:1,False:1,Int:1,Char:1,Maybe:1,Nothing:1,String:1}},c:[{cN:"comment",b:"--",e:"$"},{cN:"comment",b:"{-",e:"-}"},hljs.ASM,hljs.QSM,{cN:"import",b:"\\bimport",e:"$",k:{"import":1,qualified:1,as:1,hiding:1},c:[b]},{cN:"module",b:"\\bmodule",e:"where",k:{module:1,where:1},c:[b]},{cN:"class",b:"\\b(class|instance|data|(new)?type)",e:"(where|$)",k:{"class":1,where:1,instance:1,data:1,type:1,newtype:1,deriving:1},c:[a]},hljs.CNM,{cN:"shebang",b:"#!\\/usr\\/bin\\/env runhaskell",e:"$"},a,{cN:"title",b:"^[_a-z][\\w\\']*"}]}}}();hljs.LANGUAGES.python=function(){var c={cN:"string",b:"u?r?'''",e:"'''",r:10};var b={cN:"string",b:'u?r?"""',e:'"""',r:10};var a={cN:"string",b:"(u|r|ur)'",e:"'",c:[hljs.BE],r:10};var f={cN:"string",b:'(u|r|ur)"',e:'"',c:[hljs.BE],r:10};var d={cN:"title",b:hljs.UIR};var e={cN:"params",b:"\\(",e:"\\)",c:[c,b,a,f,hljs.ASM,hljs.QSM]};return{dM:{k:{keyword:{and:1,elif:1,is:1,global:1,as:1,"in":1,"if":1,from:1,raise:1,"for":1,except:1,"finally":1,print:1,"import":1,pass:1,"return":1,exec:1,"else":1,"break":1,not:1,"with":1,"class":1,assert:1,yield:1,"try":1,"while":1,"continue":1,del:1,or:1,def:1,lambda:1,nonlocal:10},built_in:{None:1,True:1,False:1,Ellipsis:1,NotImplemented:1}},i:"(</|->|\\?)",c:[hljs.HCM,c,b,a,f,hljs.ASM,hljs.QSM,{cN:"function",b:"\\bdef ",e:":",i:"$",k:{def:1},c:[d,e],r:10},{cN:"class",b:"\\bclass ",e:":",i:"[${]",k:{"class":1},c:[d,e],r:10},hljs.CNM,{cN:"decorator",b:"@",e:"$"}]}}}();hljs.LANGUAGES.smalltalk=function(){var b="[a-z][a-zA-Z0-9_]*";var c={cN:"char",b:"\\$.{1}"};var a={cN:"symbol",b:"#"+hljs.UIR};return{dM:{k:{self:1,"super":1,nil:1,"true":1,"false":1,thisContext:1},c:[{cN:"comment",b:'"',e:'"',r:0},hljs.ASM,{cN:"class",b:"\\b[A-Z][A-Za-z0-9_]*",r:0},{cN:"method",b:b+":"},hljs.CNM,a,c,{cN:"localvars",b:"\\|\\s*(("+b+")\\s*)+\\|"},{cN:"array",b:"\\#\\(",e:"\\)",c:[hljs.ASM,c,hljs.CNM,a]}]}}}();hljs.LANGUAGES.tex=function(){var c={cN:"command",b:"\\\\[a-zA-Zа-яА-я]+[\\*]?",r:10};var b={cN:"command",b:"\\\\[^a-zA-Zа-яА-я0-9]",r:0};var a={cN:"special",b:"[{}\\[\\]\\&#~]",r:0};return{dM:{c:[{b:"\\\\[a-zA-Zа-яА-я]+[\\*]? *= *-?\\d*\\.?\\d+(pt|pc|mm|cm|in|dd|cc|ex|em)?",rB:true,c:[c,b,{cN:"number",b:" *=",e:"-?\\d*\\.?\\d+(pt|pc|mm|cm|in|dd|cc|ex|em)?",eB:true}],r:10},c,b,a,{cN:"formula",b:"\\$\\$",e:"\\$\\$",c:[c,b,a],r:0},{cN:"formula",b:"\\$",e:"\\$",c:[c,b,a],r:0},{cN:"comment",b:"%",e:"$",r:0}]}}}();hljs.LANGUAGES.sql={cI:true,dM:{i:"[^\\s]",c:[{cN:"operator",b:"(begin|start|commit|rollback|savepoint|lock|alter|create|drop|rename|call|delete|do|handler|insert|load|replace|select|truncate|update|set|show|pragma)\\b",e:";|$",k:{keyword:{all:1,partial:1,global:1,month:1,current_timestamp:1,using:1,go:1,revoke:1,smallint:1,indicator:1,"end-exec":1,disconnect:1,zone:1,"with":1,character:1,assertion:1,to:1,add:1,current_user:1,usage:1,input:1,local:1,alter:1,match:1,collate:1,real:1,then:1,rollback:1,get:1,read:1,timestamp:1,session_user:1,not:1,integer:1,bit:1,unique:1,day:1,minute:1,desc:1,insert:1,execute:1,like:1,ilike:2,level:1,decimal:1,drop:1,"continue":1,isolation:1,found:1,where:1,constraints:1,domain:1,right:1,national:1,some:1,module:1,transaction:1,relative:1,second:1,connect:1,escape:1,close:1,system_user:1,"for":1,deferred:1,section:1,cast:1,current:1,sqlstate:1,allocate:1,intersect:1,deallocate:1,numeric:1,"public":1,preserve:1,full:1,"goto":1,initially:1,asc:1,no:1,key:1,output:1,collation:1,group:1,by:1,union:1,session:1,both:1,last:1,language:1,constraint:1,column:1,of:1,space:1,foreign:1,deferrable:1,prior:1,connection:1,unknown:1,action:1,commit:1,view:1,or:1,first:1,into:1,"float":1,year:1,primary:1,cascaded:1,except:1,restrict:1,set:1,references:1,names:1,table:1,outer:1,open:1,select:1,size:1,are:1,rows:1,from:1,prepare:1,distinct:1,leading:1,create:1,only:1,next:1,inner:1,authorization:1,schema:1,corresponding:1,option:1,declare:1,precision:1,immediate:1,"else":1,timezone_minute:1,external:1,varying:1,translation:1,"true":1,"case":1,exception:1,join:1,hour:1,"default":1,"double":1,scroll:1,value:1,cursor:1,descriptor:1,values:1,dec:1,fetch:1,procedure:1,"delete":1,and:1,"false":1,"int":1,is:1,describe:1,"char":1,as:1,at:1,"in":1,varchar:1,"null":1,trailing:1,any:1,absolute:1,current_time:1,end:1,grant:1,privileges:1,when:1,cross:1,check:1,write:1,current_date:1,pad:1,begin:1,temporary:1,exec:1,time:1,update:1,catalog:1,user:1,sql:1,date:1,on:1,identity:1,timezone_hour:1,natural:1,whenever:1,interval:1,work:1,order:1,cascade:1,diagnostics:1,nchar:1,having:1,left:1,call:1,"do":1,handler:1,load:1,replace:1,truncate:1,start:1,lock:1,show:1,pragma:1},aggregate:{count:1,sum:1,min:1,max:1,avg:1}},c:[{cN:"string",b:"'",e:"'",c:[hljs.BE,{b:"''"}],r:0},{cN:"string",b:'"',e:'"',c:[hljs.BE,{b:'""'}],r:0},{cN:"string",b:"`",e:"`",c:[hljs.BE]},hljs.CNM,{b:"\\n"}]},hljs.CBLCLM,{cN:"comment",b:"--",e:"$"}]}};hljs.LANGUAGES.ini={cI:true,dM:{i:"[^\\s]",c:[{cN:"comment",b:";",e:"$"},{cN:"title",b:"^\\[",e:"\\]"},{cN:"setting",b:"^[a-z0-9_\\[\\]]+[ \\t]*=[ \\t]*",e:"$",c:[{cN:"value",eW:true,k:{on:1,off:1,"true":1,"false":1,yes:1,no:1},c:[hljs.QSM,hljs.NM]}]}]}};hljs.LANGUAGES.perl=function(){var c={getpwent:1,getservent:1,quotemeta:1,msgrcv:1,scalar:1,kill:1,dbmclose:1,undef:1,lc:1,ma:1,syswrite:1,tr:1,send:1,umask:1,sysopen:1,shmwrite:1,vec:1,qx:1,utime:1,local:1,oct:1,semctl:1,localtime:1,readpipe:1,"do":1,"return":1,format:1,read:1,sprintf:1,dbmopen:1,pop:1,getpgrp:1,not:1,getpwnam:1,rewinddir:1,qq:1,fileno:1,qw:1,endprotoent:1,wait:1,sethostent:1,bless:1,s:1,opendir:1,"continue":1,each:1,sleep:1,endgrent:1,shutdown:1,dump:1,chomp:1,connect:1,getsockname:1,die:1,socketpair:1,close:1,flock:1,exists:1,index:1,shmget:1,sub:1,"for":1,endpwent:1,redo:1,lstat:1,msgctl:1,setpgrp:1,abs:1,exit:1,select:1,print:1,ref:1,gethostbyaddr:1,unshift:1,fcntl:1,syscall:1,"goto":1,getnetbyaddr:1,join:1,gmtime:1,symlink:1,semget:1,splice:1,x:1,getpeername:1,recv:1,log:1,setsockopt:1,cos:1,last:1,reverse:1,gethostbyname:1,getgrnam:1,study:1,formline:1,endhostent:1,times:1,chop:1,length:1,gethostent:1,getnetent:1,pack:1,getprotoent:1,getservbyname:1,rand:1,mkdir:1,pos:1,chmod:1,y:1,substr:1,endnetent:1,printf:1,next:1,open:1,msgsnd:1,readdir:1,use:1,unlink:1,getsockopt:1,getpriority:1,rindex:1,wantarray:1,hex:1,system:1,getservbyport:1,endservent:1,"int":1,chr:1,untie:1,rmdir:1,prototype:1,tell:1,listen:1,fork:1,shmread:1,ucfirst:1,setprotoent:1,"else":1,sysseek:1,link:1,getgrgid:1,shmctl:1,waitpid:1,unpack:1,getnetbyname:1,reset:1,chdir:1,grep:1,split:1,require:1,caller:1,lcfirst:1,until:1,warn:1,"while":1,values:1,shift:1,telldir:1,getpwuid:1,my:1,getprotobynumber:1,"delete":1,and:1,sort:1,uc:1,defined:1,srand:1,accept:1,"package":1,seekdir:1,getprotobyname:1,semop:1,our:1,rename:1,seek:1,"if":1,q:1,chroot:1,sysread:1,setpwent:1,no:1,crypt:1,getc:1,chown:1,sqrt:1,write:1,setnetent:1,setpriority:1,foreach:1,tie:1,sin:1,msgget:1,map:1,stat:1,getlogin:1,unless:1,elsif:1,truncate:1,exec:1,keys:1,glob:1,tied:1,closedir:1,ioctl:1,socket:1,readlink:1,"eval":1,xor:1,readline:1,binmode:1,setservent:1,eof:1,ord:1,bind:1,alarm:1,pipe:1,atan2:1,getgrent:1,exp:1,time:1,push:1,setgrent:1,gt:1,lt:1,or:1,ne:1,m:1};var d={cN:"subst",b:"[$@]\\{",e:"}",k:c,r:10};var b={cN:"variable",b:"\\$\\d"};var a={cN:"variable",b:"[\\$\\%\\@\\*](\\^\\w\\b|#\\w+(\\:\\:\\w+)*|[^\\s\\w{]|{\\w+}|\\w+(\\:\\:\\w*)*)"};var f=[hljs.BE,d,b,a];var e=[hljs.HCM,{cN:"comment",b:"^(__END__|__DATA__)",e:"\\n$",r:5},{cN:"string",b:"q[qwxr]?\\s*\\(",e:"\\)",c:f,r:5},{cN:"string",b:"q[qwxr]?\\s*\\[",e:"\\]",c:f,r:5},{cN:"string",b:"q[qwxr]?\\s*\\{",e:"\\}",c:f,r:5},{cN:"string",b:"q[qwxr]?\\s*\\|",e:"\\|",c:f,r:5},{cN:"string",b:"q[qwxr]?\\s*\\<",e:"\\>",c:f,r:5},{cN:"string",b:"qw\\s+q",e:"q",c:f,r:5},{cN:"string",b:"'",e:"'",c:[hljs.BE],r:0},{cN:"string",b:'"',e:'"',c:f,r:0},{cN:"string",b:"`",e:"`",c:[hljs.BE]},{cN:"string",b:"{\\w+}",r:0},{cN:"string",b:"-?\\w+\\s*\\=\\>",r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{cN:"regexp",b:"(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*",r:10},{cN:"regexp",b:"(m|qr)?/",e:"/[a-z]*",c:[hljs.BE],r:0},{cN:"sub",b:"\\bsub\\b",e:"(\\s*\\(.*?\\))?[;{]",k:{sub:1},r:5},b,a,{cN:"operator",b:"-\\w\\b",r:0},{cN:"pod",b:"\\=\\w",e:"\\=cut"}];d.c=e;return{dM:{k:c,c:e}}}();hljs.LANGUAGES.scala=function(){var a={cN:"annotation",b:"@[A-Za-z]+"};var b={cN:"string",b:'u?r?"""',e:'"""',r:10};return{dM:{k:{type:1,yield:1,lazy:1,override:1,def:1,"with":1,val:1,"var":1,"false":1,"true":1,sealed:1,"abstract":1,"private":1,trait:1,object:1,"null":1,"if":1,"for":1,"while":1,"throw":1,"finally":1,"protected":1,"extends":1,"import":1,"final":1,"return":1,"else":1,"break":1,"new":1,"catch":1,"super":1,"class":1,"case":1,"package":1,"default":1,"try":1,"this":1,match:1,"continue":1,"throws":1},c:[{cN:"javadoc",b:"/\\*\\*",e:"\\*/",c:[{cN:"javadoctag",b:"@[A-Za-z]+"}],r:10},hljs.CLCM,hljs.CBLCLM,hljs.ASM,hljs.QSM,b,{cN:"class",b:"((case )?class |object |trait )",e:"({|$)",i:":",k:{"case":1,"class":1,trait:1,object:1},c:[{b:"(extends|with)",k:{"extends":1,"with":1},r:10},{cN:"title",b:hljs.UIR},{cN:"params",b:"\\(",e:"\\)",c:[hljs.ASM,hljs.QSM,b,a]}]},hljs.CNM,a]}}}();hljs.LANGUAGES.cmake={cI:true,dM:{k:{add_custom_command:2,add_custom_target:2,add_definitions:2,add_dependencies:2,add_executable:2,add_library:2,add_subdirectory:2,add_executable:2,add_library:2,add_subdirectory:2,add_test:2,aux_source_directory:2,"break":1,build_command:2,cmake_minimum_required:3,cmake_policy:3,configure_file:1,create_test_sourcelist:1,define_property:1,"else":1,elseif:1,enable_language:2,enable_testing:2,endforeach:1,endfunction:1,endif:1,endmacro:1,endwhile:1,execute_process:2,"export":1,find_file:1,find_library:2,find_package:2,find_path:1,find_program:1,fltk_wrap_ui:2,foreach:1,"function":1,get_cmake_property:3,get_directory_property:1,get_filename_component:1,get_property:1,get_source_file_property:1,get_target_property:1,get_test_property:1,"if":1,include:1,include_directories:2,include_external_msproject:1,include_regular_expression:2,install:1,link_directories:1,load_cache:1,load_command:1,macro:1,mark_as_advanced:1,message:1,option:1,output_required_files:1,project:1,qt_wrap_cpp:2,qt_wrap_ui:2,remove_definitions:2,"return":1,separate_arguments:1,set:1,set_directory_properties:1,set_property:1,set_source_files_properties:1,set_target_properties:1,set_tests_properties:1,site_name:1,source_group:1,string:1,target_link_libraries:2,try_compile:2,try_run:2,unset:1,variable_watch:2,"while":1,build_name:1,exec_program:1,export_library_dependencies:1,install_files:1,install_programs:1,install_targets:1,link_libraries:1,make_directory:1,remove:1,subdir_depends:1,subdirs:1,use_mangled_mesa:1,utility_source:1,variable_requires:1,write_file:1},c:[{cN:"envvar",b:"\\${",e:"}"},hljs.HCM,hljs.QSM,hljs.NM]}};hljs.LANGUAGES.objectivec=function(){var a={keyword:{"false":1,"int":1,"float":1,"while":1,"private":1,"char":1,"catch":1,"export":1,sizeof:2,typedef:2,"const":1,struct:1,"for":1,union:1,unsigned:1,"long":1,"volatile":2,"static":1,"protected":1,bool:1,mutable:1,"if":1,"public":1,"do":1,"return":1,"goto":1,"void":2,"enum":1,"else":1,"break":1,extern:1,"true":1,"class":1,asm:1,"case":1,"short":1,"default":1,"double":1,"throw":1,register:1,explicit:1,signed:1,typename:1,"try":1,"this":1,"switch":1,"continue":1,wchar_t:1,inline:1,readonly:1,assign:1,property:1,protocol:10,self:1,"synchronized":1,end:1,synthesize:50,id:1,optional:1,required:1,implementation:10,nonatomic:1,"interface":1,"super":1,unichar:1,"finally":2,dynamic:2,nil:1},built_in:{YES:5,NO:5,NULL:1,IBOutlet:50,IBAction:50,NSString:50,NSDictionary:50,CGRect:50,CGPoint:50,NSRange:50,release:1,retain:1,autorelease:50,UIButton:50,UILabel:50,UITextView:50,UIWebView:50,MKMapView:50,UISegmentedControl:50,NSObject:50,UITableViewDelegate:50,UITableViewDataSource:50,NSThread:50,UIActivityIndicator:50,UITabbar:50,UIToolBar:50,UIBarButtonItem:50,UIImageView:50,NSAutoreleasePool:50,UITableView:50,BOOL:1,NSInteger:20,CGFloat:20,NSException:50,NSLog:50,NSMutableString:50,NSMutableArray:50,NSMutableDictionary:50,NSURL:50}};return{dM:{k:a,i:"</",c:[hljs.CLCM,hljs.CBLCLM,hljs.CNM,hljs.QSM,{cN:"string",b:"'",e:"[^\\\\]'",i:"[^\\\\][^']"},{cN:"preprocessor",b:"#import",e:"$",c:[{cN:"title",b:'"',e:'"'},{cN:"title",b:"<",e:">"}]},{cN:"preprocessor",b:"#",e:"$"},{cN:"class",b:"interface|class|protocol|implementation",e:"({|$)",k:{"interface":1,"class":1,protocol:5,implementation:5},c:[{cN:"id",b:hljs.UIR}]}]}}}();hljs.LANGUAGES.nginx=function(){var c={cN:"variable",b:"\\$\\d+"};var b={cN:"variable",b:"\\${",e:"}"};var a={cN:"variable",b:"[\\$\\@]"+hljs.UIR};return{dM:{c:[hljs.HCM,{b:hljs.UIR,e:";|{",rE:true,k:{accept_mutex:1,accept_mutex_delay:1,access_log:1,add_after_body:1,add_before_body:1,add_header:1,addition_types:1,alias:1,allow:1,ancient_browser:1,ancient_browser:1,ancient_browser_value:1,ancient_browser_value:1,auth_basic:1,auth_basic_user_file:1,autoindex:1,autoindex_exact_size:1,autoindex_localtime:1,"break":1,charset:1,charset:1,charset_map:1,charset_map:1,charset_types:1,charset_types:1,client_body_buffer_size:1,client_body_in_file_only:1,client_body_in_single_buffer:1,client_body_temp_path:1,client_body_timeout:1,client_header_buffer_size:1,client_header_timeout:1,client_max_body_size:1,connection_pool_size:1,connections:1,create_full_put_path:1,daemon:1,dav_access:1,dav_methods:1,debug_connection:1,debug_points:1,default_type:1,deny:1,directio:1,directio_alignment:1,echo:1,echo_after_body:1,echo_before_body:1,echo_blocking_sleep:1,echo_duplicate:1,echo_end:1,echo_exec:1,echo_flush:1,echo_foreach_split:1,echo_location:1,echo_location_async:1,echo_read_request_body:1,echo_request_body:1,echo_reset_timer:1,echo_sleep:1,echo_subrequest:1,echo_subrequest_async:1,empty_gif:1,empty_gif:1,env:1,error_log:1,error_log:1,error_page:1,events:1,expires:1,fastcgi_bind:1,fastcgi_buffer_size:1,fastcgi_buffers:1,fastcgi_busy_buffers_size:1,fastcgi_cache:1,fastcgi_cache_key:1,fastcgi_cache_methods:1,fastcgi_cache_min_uses:1,fastcgi_cache_path:1,fastcgi_cache_use_stale:1,fastcgi_cache_valid:1,fastcgi_catch_stderr:1,fastcgi_connect_timeout:1,fastcgi_hide_header:1,fastcgi_ignore_client_abort:1,fastcgi_ignore_headers:1,fastcgi_index:1,fastcgi_intercept_errors:1,fastcgi_max_temp_file_size:1,fastcgi_next_upstream:1,fastcgi_param:1,fastcgi_pass:1,fastcgi_pass_header:1,fastcgi_pass_request_body:1,fastcgi_pass_request_headers:1,fastcgi_read_timeout:1,fastcgi_send_lowat:1,fastcgi_send_timeout:1,fastcgi_split_path_info:1,fastcgi_store:1,fastcgi_store_access:1,fastcgi_temp_file_write_size:1,fastcgi_temp_path:1,fastcgi_upstream_fail_timeout:1,fastcgi_upstream_max_fails:1,flv:1,geo:1,geo:1,geoip_city:1,geoip_country:1,gzip:1,gzip_buffers:1,gzip_comp_level:1,gzip_disable:1,gzip_hash:1,gzip_http_version:1,gzip_min_length:1,gzip_no_buffer:1,gzip_proxied:1,gzip_static:1,gzip_types:1,gzip_vary:1,gzip_window:1,http:1,"if":1,if_modified_since:1,ignore_invalid_headers:1,image_filter:1,image_filter_buffer:1,image_filter_jpeg_quality:1,image_filter_transparency:1,include:1,index:1,internal:1,ip_hash:1,js:1,js_load:1,js_require:1,js_utf8:1,keepalive_requests:1,keepalive_timeout:1,kqueue_changes:1,kqueue_events:1,large_client_header_buffers:1,limit_conn:1,limit_conn_log_level:1,limit_except:1,limit_rate:1,limit_rate_after:1,limit_req:1,limit_req_log_level:1,limit_req_zone:1,limit_zone:1,lingering_time:1,lingering_timeout:1,listen:1,location:1,lock_file:1,log_format:1,log_not_found:1,log_subrequest:1,map:1,map_hash_bucket_size:1,map_hash_max_size:1,master_process:1,memcached_bind:1,memcached_buffer_size:1,memcached_connect_timeout:1,memcached_next_upstream:1,memcached_pass:1,memcached_read_timeout:1,memcached_send_timeout:1,memcached_upstream_fail_timeout:1,memcached_upstream_max_fails:1,merge_slashes:1,min_delete_depth:1,modern_browser:1,modern_browser:1,modern_browser_value:1,modern_browser_value:1,more_clear_headers:1,more_clear_input_headers:1,more_set_headers:1,more_set_input_headers:1,msie_padding:1,msie_refresh:1,multi_accept:1,open_file_cache:1,open_file_cache_errors:1,open_file_cache_events:1,open_file_cache_min_uses:1,open_file_cache_retest:1,open_file_cache_valid:1,open_log_file_cache:1,optimize_server_names:1,output_buffers:1,override_charset:1,override_charset:1,perl:1,perl_modules:1,perl_require:1,perl_set:1,pid:1,port_in_redirect:1,post_action:1,postpone_gzipping:1,postpone_output:1,proxy_bind:1,proxy_buffer_size:1,proxy_buffering:1,proxy_buffers:1,proxy_busy_buffers_size:1,proxy_cache:1,proxy_cache_key:1,proxy_cache_methods:1,proxy_cache_min_uses:1,proxy_cache_path:1,proxy_cache_use_stale:1,proxy_cache_valid:1,proxy_connect_timeout:1,proxy_headers_hash_bucket_size:1,proxy_headers_hash_max_size:1,proxy_hide_header:1,proxy_ignore_client_abort:1,proxy_ignore_headers:1,proxy_intercept_errors:1,proxy_max_temp_file_size:1,proxy_method:1,proxy_next_upstream:1,proxy_pass:1,proxy_pass_header:1,proxy_pass_request_body:1,proxy_pass_request_headers:1,proxy_read_timeout:1,proxy_redirect:1,proxy_send_lowat:1,proxy_send_timeout:1,proxy_set_body:1,proxy_set_header:1,proxy_store:1,proxy_store_access:1,proxy_temp_file_write_size:1,proxy_temp_path:1,proxy_upstream_fail_timeout:1,proxy_upstream_max_fails:1,push_authorized_channels_only:1,push_channel_group:1,push_max_channel_id_length:1,push_max_channel_subscribers:1,push_max_message_buffer_length:1,push_max_reserved_memory:1,push_message_buffer_length:1,push_message_timeout:1,push_min_message_buffer_length:1,push_min_message_recipients:1,push_publisher:1,push_store_messages:1,push_subscriber:1,push_subscriber_concurrency:1,random_index:1,read_ahead:1,real_ip_header:1,recursive_error_pages:1,request_pool_size:1,reset_timedout_connection:1,resolver:1,resolver_timeout:1,"return":1,rewrite:1,rewrite_log:1,root:1,satisfy:1,satisfy_any:1,send_lowat:1,send_timeout:1,sendfile:1,sendfile_max_chunk:1,server:1,server:1,server_name:1,server_name_in_redirect:1,server_names_hash_bucket_size:1,server_names_hash_max_size:1,server_tokens:1,set:1,set_real_ip_from:1,source_charset:1,source_charset:1,ssi:1,ssi_ignore_recycled_buffers:1,ssi_min_file_chunk:1,ssi_silent_errors:1,ssi_types:1,ssi_value_length:1,ssl:1,ssl_certificate:1,ssl_certificate_key:1,ssl_ciphers:1,ssl_client_certificate:1,ssl_crl:1,ssl_dhparam:1,ssl_prefer_server_ciphers:1,ssl_protocols:1,ssl_session_cache:1,ssl_session_timeout:1,ssl_verify_client:1,ssl_verify_depth:1,sub_filter:1,sub_filter_once:1,sub_filter_types:1,tcp_nodelay:1,tcp_nopush:1,timer_resolution:1,try_files:1,types:1,types_hash_bucket_size:1,types_hash_max_size:1,underscores_in_headers:1,uninitialized_variable_warn:1,upstream:1,use:1,user:1,userid:1,userid:1,userid_domain:1,userid_domain:1,userid_expires:1,userid_expires:1,userid_mark:1,userid_name:1,userid_name:1,userid_p3p:1,userid_p3p:1,userid_path:1,userid_path:1,userid_service:1,userid_service:1,valid_referers:1,variables_hash_bucket_size:1,variables_hash_max_size:1,worker_connections:1,worker_cpu_affinity:1,worker_priority:1,worker_processes:1,worker_rlimit_core:1,worker_rlimit_nofile:1,worker_rlimit_sigpending:1,working_directory:1,xml_entities:1,xslt_stylesheet:1,xslt_types:1},r:0,c:[hljs.HCM,{b:"\\s",e:"[;{]",rB:true,rE:true,l:"[a-z/]+",k:{built_in:{on:1,off:1,yes:1,no:1,"true":1,"false":1,none:1,blocked:1,debug:1,info:1,notice:1,warn:1,error:1,crit:1,select:1,permanent:1,redirect:1,kqueue:1,rtsig:1,epoll:1,poll:1,"/dev/poll":1}},r:0,c:[hljs.HCM,{cN:"string",b:'"',e:'"',c:[hljs.BE,c,b,a],r:0},{cN:"string",b:"'",e:"'",c:[hljs.BE,c,b,a],r:0},{cN:"string",b:"([a-z]+):/",e:"[;\\s]",rE:true},{cN:"regexp",b:"\\s\\^",e:"\\s|{|;",rE:true,c:[hljs.BE,c,b,a]},{cN:"regexp",b:"~\\*?\\s+",e:"\\s|{|;",rE:true,c:[hljs.BE,c,b,a]},{cN:"regexp",b:"\\*(\\.[a-z\\-]+)+",c:[hljs.BE,c,b,a]},{cN:"regexp",b:"([a-z\\-]+\\.)+\\*",c:[hljs.BE,c,b,a]},{cN:"number",b:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b"},{cN:"number",b:"\\s\\d+[kKmMgGdshdwy]*\\b",r:0},c,b,a]}]}]}}}();hljs.LANGUAGES.erlang_repl={dM:{k:{special_functions:{spawn:10,spawn_link:10,self:2},reserved:{after:1,and:1,andalso:5,band:1,begin:1,bnot:1,bor:1,bsl:1,bsr:1,bxor:1,"case":1,"catch":0,cond:1,div:1,end:1,fun:0,"if":0,let:1,not:0,of:1,or:1,orelse:5,query:1,receive:0,rem:1,"try":0,when:1,xor:1}},c:[{cN:"input_number",b:"^[0-9]+> ",r:10},{cN:"comment",b:"%",e:"$"},hljs.NM,hljs.ASM,hljs.QSM,{cN:"constant",b:"\\?(::)?([A-Z]\\w*(::)?)+"},{cN:"arrow",b:"->"},{cN:"ok",b:"ok"},{cN:"exclamation_mark",b:"!"},{cN:"function_or_atom",b:"(\\b[a-z'][a-zA-Z0-9_']*:[a-z'][a-zA-Z0-9_']*)|(\\b[a-z'][a-zA-Z0-9_']*)",r:0},{cN:"variable",b:"[A-Z][a-zA-Z0-9_']*",r:0}]}};hljs.LANGUAGES.django=function(){function c(f,e){return(e==undefined||(!f.cN&&e.cN=="tag")||f.cN=="value")}function d(j,e){var h={};for(var g in j){if(g!="contains"){h[g]=j[g]}var k=[];for(var f=0;j.c&&f<j.c.length;f++){k.push(d(j.c[f],j))}if(c(j,e)){k=b.concat(k)}if(k.length){h.c=k}}return h}var a={cN:"filter",b:"\\|[A-Za-z]+\\:?",eE:true,k:{truncatewords:1,removetags:1,linebreaksbr:1,yesno:1,get_digit:1,timesince:1,random:1,striptags:1,filesizeformat:1,escape:1,linebreaks:1,length_is:1,ljust:1,rjust:1,cut:1,urlize:1,fix_ampersands:1,title:1,floatformat:1,capfirst:1,pprint:1,divisibleby:1,add:1,make_list:1,unordered_list:1,urlencode:1,timeuntil:1,urlizetrunc:1,wordcount:1,stringformat:1,linenumbers:1,slice:1,date:1,dictsort:1,dictsortreversed:1,default_if_none:1,pluralize:1,lower:1,join:1,center:1,"default":1,truncatewords_html:1,upper:1,length:1,phone2numeric:1,wordwrap:1,time:1,addslashes:1,slugify:1,first:1},c:[{cN:"argument",b:'"',e:'"'}]};var b=[{cN:"template_comment",b:"{%\\s*comment\\s*%}",e:"{%\\s*endcomment\\s*%}"},{cN:"template_comment",b:"{#",e:"#}"},{cN:"template_tag",b:"{%",e:"%}",k:{comment:1,endcomment:1,load:1,templatetag:1,ifchanged:1,endifchanged:1,"if":1,endif:1,firstof:1,"for":1,endfor:1,"in":1,ifnotequal:1,endifnotequal:1,widthratio:1,"extends":1,include:1,spaceless:1,endspaceless:1,regroup:1,by:1,as:1,ifequal:1,endifequal:1,ssi:1,now:1,"with":1,cycle:1,url:1,filter:1,endfilter:1,debug:1,block:1,endblock:1,"else":1},c:[a]},{cN:"variable",b:"{{",e:"}}",c:[a]}];return{cI:true,dM:d(hljs.LANGUAGES.xml.dM)}}();hljs.LANGUAGES.delphi=function(){var a={and:1,safecall:1,cdecl:1,then:1,string:1,exports:1,library:1,not:1,pascal:1,set:1,virtual:1,file:1,"in":1,array:1,label:1,packed:1,"end.":1,index:1,"while":1,"const":1,raise:1,"for":1,to:1,implementation:1,"with":1,except:1,overload:1,destructor:1,downto:1,"finally":1,program:1,exit:1,unit:1,inherited:1,override:1,"if":1,type:1,until:1,"function":1,"do":1,begin:1,repeat:1,"goto":1,nil:1,far:1,initialization:1,object:1,"else":1,"var":1,uses:1,external:1,resourcestring:1,"interface":1,end:1,finalization:1,"class":1,asm:1,mod:1,"case":1,on:1,shr:1,shl:1,of:1,register:1,xorwrite:1,threadvar:1,"try":1,record:1,near:1,stored:1,constructor:1,stdcall:1,inline:1,div:1,out:1,or:1,procedure:1};var c={safecall:1,stdcall:1,pascal:1,stored:1,"const":1,implementation:1,finalization:1,except:1,to:1,"finally":1,program:1,inherited:1,override:1,then:1,exports:1,string:1,read:1,not:1,mod:1,shr:1,"try":1,div:1,shl:1,set:1,library:1,message:1,packed:1,index:1,"for":1,near:1,overload:1,label:1,downto:1,exit:1,"public":1,"goto":1,"interface":1,asm:1,on:1,of:1,constructor:1,or:1,"private":1,array:1,unit:1,raise:1,destructor:1,"var":1,type:1,until:1,"function":1,"else":1,external:1,"with":1,"case":1,"default":1,record:1,"while":1,"protected":1,property:1,procedure:1,published:1,and:1,cdecl:1,"do":1,threadvar:1,file:1,"in":1,"if":1,end:1,virtual:1,write:1,far:1,out:1,begin:1,repeat:1,nil:1,initialization:1,object:1,uses:1,resourcestring:1,"class":1,register:1,xorwrite:1,inline:1,"static":1};var f={cN:"comment",b:"{",e:"}",r:0};var e={cN:"comment",b:"\\(\\*",e:"\\*\\)",r:10};var d={cN:"string",b:"'",e:"'",c:[{b:"''"}],r:0};var b={cN:"string",b:"(#\\d+)+"};var g={cN:"function",b:"(procedure|constructor|destructor|function)\\b",e:"[:;]",k:{"function":1,constructor:10,destructor:10,procedure:10},c:[{cN:"title",b:hljs.IR},{cN:"params",b:"\\(",e:"\\)",k:a,c:[d,b]},f,e]};return{cI:true,dM:{k:a,i:'("|\\$[G-Zg-z]|\\/\\*|</)',c:[f,e,hljs.CLCM,d,b,hljs.NM,g,{cN:"class",b:"=\\bclass\\b",e:"end;",k:c,c:[d,b,f,e,g]}]},m:[]}}();hljs.LANGUAGES.vbscript={cI:true,dM:{k:{keyword:{call:1,"class":1,"const":1,dim:1,"do":1,loop:1,erase:1,execute:1,executeglobal:1,exit:1,"for":1,each:1,next:1,"function":1,"if":1,then:1,"else":1,on:1,error:1,option:1,explicit:1,"new":1,"private":1,property:1,let:1,get:1,"public":1,randomize:1,redim:1,rem:1,select:1,"case":1,set:1,stop:1,sub:1,"while":1,wend:1,"with":1,end:1,to:1,elseif:1,is:1,or:1,xor:1,and:1,not:1,class_initialize:1,class_terminate:1,"default":1,preserve:1,"in":1,me:1,byval:1,byref:1,step:1,resume:1,"goto":1},built_in:{lcase:1,month:1,vartype:1,instrrev:1,ubound:1,setlocale:1,getobject:1,rgb:1,getref:1,string:1,weekdayname:1,rnd:1,dateadd:1,monthname:1,now:1,day:1,minute:1,isarray:1,cbool:1,round:1,formatcurrency:1,conversions:1,csng:1,timevalue:1,second:1,year:1,space:1,abs:1,clng:1,timeserial:1,fixs:1,len:1,asc:1,isempty:1,maths:1,dateserial:1,atn:1,timer:1,isobject:1,filter:1,weekday:1,datevalue:1,ccur:1,isdate:1,instr:1,datediff:1,formatdatetime:1,replace:1,isnull:1,right:1,sgn:1,array:1,snumeric:1,log:1,cdbl:1,hex:1,chr:1,lbound:1,msgbox:1,ucase:1,getlocale:1,cos:1,cdate:1,cbyte:1,rtrim:1,join:1,hour:1,oct:1,typename:1,trim:1,strcomp:1,"int":1,createobject:1,loadpicture:1,tan:1,formatnumber:1,mid:1,scriptenginebuildversion:1,scriptengine:1,split:1,scriptengineminorversion:1,cint:1,sin:1,datepart:1,ltrim:1,sqr:1,scriptenginemajorversion:1,time:1,derived:1,"eval":1,date:1,formatpercent:1,exp:1,inputbox:1,left:1,ascw:1,chrw:1,regexp:1,server:1,response:1,request:1,cstr:1,err:1},literal:{"true":1,"false":1,"null":1,nothing:1,empty:1}},c:[{cN:"string",b:'"',e:'"',i:"\\n",c:[{b:'""'}],r:0},{cN:"comment",b:"'",e:"$"},hljs.CNM]}};hljs.LANGUAGES.apache=function(){var b={cN:"number",b:"[\\$%]\\d+"};var a={cN:"cbracket",b:"[\\$%]\\{",e:"\\}"};a.c=[a,b];return{cI:true,dM:{k:{keyword:{acceptfilter:1,acceptmutex:1,acceptpathinfo:1,accessfilename:1,action:1,addalt:1,addaltbyencoding:1,addaltbytype:1,addcharset:1,adddefaultcharset:1,adddescription:1,addencoding:1,addhandler:1,addicon:1,addiconbyencoding:1,addiconbytype:1,addinputfilter:1,addlanguage:1,addmoduleinfo:1,addoutputfilter:1,addoutputfilterbytype:1,addtype:1,alias:1,aliasmatch:1,allow:1,allowconnect:1,allowencodedslashes:1,allowoverride:1,anonymous:1,anonymous_logemail:1,anonymous_mustgiveemail:1,anonymous_nouserid:1,anonymous_verifyemail:1,authbasicauthoritative:1,authbasicprovider:1,authdbduserpwquery:1,authdbduserrealmquery:1,authdbmgroupfile:1,authdbmtype:1,authdbmuserfile:1,authdefaultauthoritative:1,authdigestalgorithm:1,authdigestdomain:1,authdigestnccheck:1,authdigestnonceformat:1,authdigestnoncelifetime:1,authdigestprovider:1,authdigestqop:1,authdigestshmemsize:1,authgroupfile:1,authldapbinddn:1,authldapbindpassword:1,authldapcharsetconfig:1,authldapcomparednonserver:1,authldapdereferencealiases:1,authldapgroupattribute:1,authldapgroupattributeisdn:1,authldapremoteuserattribute:1,authldapremoteuserisdn:1,authldapurl:1,authname:1,authnprovideralias:1,authtype:1,authuserfile:1,authzdbmauthoritative:1,authzdbmtype:1,authzdefaultauthoritative:1,authzgroupfileauthoritative:1,authzldapauthoritative:1,authzownerauthoritative:1,authzuserauthoritative:1,balancermember:1,browsermatch:1,browsermatchnocase:1,bufferedlogs:1,cachedefaultexpire:1,cachedirlength:1,cachedirlevels:1,cachedisable:1,cacheenable:1,cachefile:1,cacheignorecachecontrol:1,cacheignoreheaders:1,cacheignorenolastmod:1,cacheignorequerystring:1,cachelastmodifiedfactor:1,cachemaxexpire:1,cachemaxfilesize:1,cacheminfilesize:1,cachenegotiateddocs:1,cacheroot:1,cachestorenostore:1,cachestoreprivate:1,cgimapextension:1,charsetdefault:1,charsetoptions:1,charsetsourceenc:1,checkcaseonly:1,checkspelling:1,chrootdir:1,contentdigest:1,cookiedomain:1,cookieexpires:1,cookielog:1,cookiename:1,cookiestyle:1,cookietracking:1,coredumpdirectory:1,customlog:1,dav:1,davdepthinfinity:1,davgenericlockdb:1,davlockdb:1,davmintimeout:1,dbdexptime:1,dbdkeep:1,dbdmax:1,dbdmin:1,dbdparams:1,dbdpersist:1,dbdpreparesql:1,dbdriver:1,defaulticon:1,defaultlanguage:1,defaulttype:1,deflatebuffersize:1,deflatecompressionlevel:1,deflatefilternote:1,deflatememlevel:1,deflatewindowsize:1,deny:1,directoryindex:1,directorymatch:1,directoryslash:1,documentroot:1,dumpioinput:1,dumpiologlevel:1,dumpiooutput:1,enableexceptionhook:1,enablemmap:1,enablesendfile:1,errordocument:1,errorlog:1,example:1,expiresactive:1,expiresbytype:1,expiresdefault:1,extendedstatus:1,extfilterdefine:1,extfilteroptions:1,fileetag:1,filterchain:1,filterdeclare:1,filterprotocol:1,filterprovider:1,filtertrace:1,forcelanguagepriority:1,forcetype:1,forensiclog:1,gracefulshutdowntimeout:1,group:1,header:1,headername:1,hostnamelookups:1,identitycheck:1,identitychecktimeout:1,imapbase:1,imapdefault:1,imapmenu:1,include:1,indexheadinsert:1,indexignore:1,indexoptions:1,indexorderdefault:1,indexstylesheet:1,isapiappendlogtoerrors:1,isapiappendlogtoquery:1,isapicachefile:1,isapifakeasync:1,isapilognotsupported:1,isapireadaheadbuffer:1,keepalive:1,keepalivetimeout:1,languagepriority:1,ldapcacheentries:1,ldapcachettl:1,ldapconnectiontimeout:1,ldapopcacheentries:1,ldapopcachettl:1,ldapsharedcachefile:1,ldapsharedcachesize:1,ldaptrustedclientcert:1,ldaptrustedglobalcert:1,ldaptrustedmode:1,ldapverifyservercert:1,limitinternalrecursion:1,limitrequestbody:1,limitrequestfields:1,limitrequestfieldsize:1,limitrequestline:1,limitxmlrequestbody:1,listen:1,listenbacklog:1,loadfile:1,loadmodule:1,lockfile:1,logformat:1,loglevel:1,maxclients:1,maxkeepaliverequests:1,maxmemfree:1,maxrequestsperchild:1,maxrequestsperthread:1,maxspareservers:1,maxsparethreads:1,maxthreads:1,mcachemaxobjectcount:1,mcachemaxobjectsize:1,mcachemaxstreamingbuffer:1,mcacheminobjectsize:1,mcacheremovalalgorithm:1,mcachesize:1,metadir:1,metafiles:1,metasuffix:1,mimemagicfile:1,minspareservers:1,minsparethreads:1,mmapfile:1,mod_gzip_on:1,mod_gzip_add_header_count:1,mod_gzip_keep_workfiles:1,mod_gzip_dechunk:1,mod_gzip_min_http:1,mod_gzip_minimum_file_size:1,mod_gzip_maximum_file_size:1,mod_gzip_maximum_inmem_size:1,mod_gzip_temp_dir:1,mod_gzip_item_include:1,mod_gzip_item_exclude:1,mod_gzip_command_version:1,mod_gzip_can_negotiate:1,mod_gzip_handle_methods:1,mod_gzip_static_suffix:1,mod_gzip_send_vary:1,mod_gzip_update_static:1,modmimeusepathinfo:1,multiviewsmatch:1,namevirtualhost:1,noproxy:1,nwssltrustedcerts:1,nwsslupgradeable:1,options:1,order:1,passenv:1,pidfile:1,protocolecho:1,proxybadheader:1,proxyblock:1,proxydomain:1,proxyerroroverride:1,proxyftpdircharset:1,proxyiobuffersize:1,proxymaxforwards:1,proxypass:1,proxypassinterpolateenv:1,proxypassmatch:1,proxypassreverse:1,proxypassreversecookiedomain:1,proxypassreversecookiepath:1,proxypreservehost:1,proxyreceivebuffersize:1,proxyremote:1,proxyremotematch:1,proxyrequests:1,proxyset:1,proxystatus:1,proxytimeout:1,proxyvia:1,readmename:1,receivebuffersize:1,redirect:1,redirectmatch:1,redirectpermanent:1,redirecttemp:1,removecharset:1,removeencoding:1,removehandler:1,removeinputfilter:1,removelanguage:1,removeoutputfilter:1,removetype:1,requestheader:1,require:2,rewritebase:1,rewritecond:10,rewriteengine:1,rewritelock:1,rewritelog:1,rewriteloglevel:1,rewritemap:1,rewriteoptions:1,rewriterule:10,rlimitcpu:1,rlimitmem:1,rlimitnproc:1,satisfy:1,scoreboardfile:1,script:1,scriptalias:1,scriptaliasmatch:1,scriptinterpretersource:1,scriptlog:1,scriptlogbuffer:1,scriptloglength:1,scriptsock:1,securelisten:1,seerequesttail:1,sendbuffersize:1,serveradmin:1,serveralias:1,serverlimit:1,servername:1,serverpath:1,serverroot:1,serversignature:1,servertokens:1,setenv:1,setenvif:1,setenvifnocase:1,sethandler:1,setinputfilter:1,setoutputfilter:1,ssienableaccess:1,ssiendtag:1,ssierrormsg:1,ssistarttag:1,ssitimeformat:1,ssiundefinedecho:1,sslcacertificatefile:1,sslcacertificatepath:1,sslcadnrequestfile:1,sslcadnrequestpath:1,sslcarevocationfile:1,sslcarevocationpath:1,sslcertificatechainfile:1,sslcertificatefile:1,sslcertificatekeyfile:1,sslciphersuite:1,sslcryptodevice:1,sslengine:1,sslhonorciperorder:1,sslmutex:1,ssloptions:1,sslpassphrasedialog:1,sslprotocol:1,sslproxycacertificatefile:1,sslproxycacertificatepath:1,sslproxycarevocationfile:1,sslproxycarevocationpath:1,sslproxyciphersuite:1,sslproxyengine:1,sslproxymachinecertificatefile:1,sslproxymachinecertificatepath:1,sslproxyprotocol:1,sslproxyverify:1,sslproxyverifydepth:1,sslrandomseed:1,sslrequire:1,sslrequiressl:1,sslsessioncache:1,sslsessioncachetimeout:1,sslusername:1,sslverifyclient:1,sslverifydepth:1,startservers:1,startthreads:1,substitute:1,suexecusergroup:1,threadlimit:1,threadsperchild:1,threadstacksize:1,timeout:1,traceenable:1,transferlog:1,typesconfig:1,unsetenv:1,usecanonicalname:1,usecanonicalphysicalport:1,user:1,userdir:1,virtualdocumentroot:1,virtualdocumentrootip:1,virtualscriptalias:1,virtualscriptaliasip:1,win32disableacceptex:1,xbithack:1},literal:{on:1,off:1}},c:[hljs.HCM,{cN:"sqbracket",b:"\\s\\[",e:"\\]$"},a,b,{cN:"tag",b:"</?",e:">"},hljs.QSM]}}}();hljs.LANGUAGES.cpp=function(){var b={keyword:{"false":1,"int":1,"float":1,"while":1,"private":1,"char":1,"catch":1,"export":1,virtual:1,operator:2,sizeof:2,dynamic_cast:2,typedef:2,const_cast:2,"const":1,struct:1,"for":1,static_cast:2,union:1,namespace:1,unsigned:1,"long":1,"throw":1,"volatile":2,"static":1,"protected":1,bool:1,template:1,mutable:1,"if":1,"public":1,friend:2,"do":1,"return":1,"goto":1,auto:1,"void":2,"enum":1,"else":1,"break":1,"new":1,extern:1,using:1,"true":1,"class":1,asm:1,"case":1,typeid:1,"short":1,reinterpret_cast:2,"default":1,"double":1,register:1,explicit:1,signed:1,typename:1,"try":1,"this":1,"switch":1,"continue":1,wchar_t:1,inline:1,"delete":1,alignof:1,char16_t:1,char32_t:1,constexpr:1,decltype:1,noexcept:1,nullptr:1,static_assert:1,thread_local:1},built_in:{std:1,string:1,cin:1,cout:1,cerr:1,clog:1,stringstream:1,istringstream:1,ostringstream:1,auto_ptr:1,deque:1,list:1,queue:1,stack:1,vector:1,map:1,set:1,bitset:1,multiset:1,multimap:1,unordered_set:1,unordered_map:1,unordered_multiset:1,unordered_multimap:1,array:1,shared_ptr:1}};var a={cN:"stl_container",b:"\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",e:">",k:b.built_in,r:10};a.c=[a];return{dM:{k:b,i:"</",c:[hljs.CLCM,hljs.CBLCLM,hljs.QSM,{cN:"string",b:"'",e:"[^\\\\]'",i:"[^\\\\][^']"},hljs.CNM,{cN:"preprocessor",b:"#",e:"$"},a]}}}();hljs.LANGUAGES.go=function(){var a={keyword:{"break":1,"default":1,func:1,"interface":1,select:1,"case":1,map:1,struct:1,chan:1,"else":1,"goto":1,"package":1,"switch":1,"const":1,fallthrough:1,"if":1,range:1,type:1,"continue":1,"for":1,"import":1,"return":1,"var":1,go:1,defer:1},constant:{"true":1,"false":1,iota:1,nil:1},typename:{bool:1,"byte":1,complex64:1,complex128:1,float32:1,float64:1,int8:1,int16:1,int32:1,int64:1,string:1,uint8:1,uint16:1,uint32:1,uint64:1,"int":1,uint:1,uintptr:1},built_in:{append:1,cap:1,close:1,complex:1,copy:1,imag:1,len:1,make:1,"new":1,panic:1,print:1,println:1,real:1,recover:1}};return{dM:{k:a,i:"</",c:[hljs.CLCM,hljs.CBLCLM,hljs.QSM,{cN:"string",b:"'",e:"[^\\\\]'"},{cN:"string",b:"`",e:"[^\\\\]`"},{cN:"number",b:"[^a-zA-Z_0-9](\\-|\\+)?\\d+(\\.\\d+|\\/\\d+)?((d|e|f|l|s)(\\+|\\-)?\\d+)?"},hljs.CNM]}}}();
− docs/home.css
@@ -1,143 +0,0 @@-/* Standard elements */-body {- font-family: sans-serif;- color: #666;- margin-bottom: 0;- padding-bottom: 0;-}-a {- color: #F40095;- text-decoration: none-}-a:hover {- text-decoration: underline;-}-li + li {- margin-top: 0.5em;-}-/* Page layout */-.wrap {- margin: auto;- width: 40em;-}-/* Header */-h1 {- font-size: 2em;- margin-bottom:0;- padding-bottom:0;- margin-top:0;- color: #F40095-}-h2 {- color: #850095;- padding-bottom: 0em;- margin-bottom: 0;-}-h3 {- color: #948091;- font-style: italic;-}-.head {- margin-top: 2em;-}-.head-logo {- height: 50px;- margin-top:5px;- float: left;- margin-right:1em-}-.head-text {- margin-left: 1em;-}-.subheadline {- font-size: 20px;- margin-bottom: 1em;- font-style: italic;-}--/* Syntax highlighting */-.example { }-.example pre { margin-top:0;-word-wrap: break-word; }-.example pre .diff { color:#555 }-.example pre code .title { color:#333 }-.example pre code .string { color:#366354 }-.example pre code .built_in { color:#397460 }-.example pre code .preprocessor { color:#4F4371 }-.example pre code .comment { color:#555 }-.example pre code .command { color:#397460 }-.example pre code .special { color:#333 }-.example pre code .formula { color:#4F4371 }-.example pre code .keyword { color:#397460 }-.example pre code .number { color:#4F4371 }-.example pre code .header { color:#555 }-.example pre code .addition { background-color:#FDD;color:#695B5B }-.example pre code .deletion { background-color:#DFD;color:#000 }-.example pre { margin:0 }-.example table { border-spacing: 1em; }-.example {}-.example .lang { font-size: small; margin-bottom: 1em; color: #999 }-.example .tab-title { cursor: pointer; }-.example .tab-title-current em { font-weight: bold; color: #555; font-style: normal }-.example .tab-title { display: inline-block; margin-right: 1em; }-.example pre { }-.example { float: left }-.example table { margin-left: -1em; }-.example td { vertical-align: top; box-shadow: 0px 0px 20px #ccc; border-radius: 5px; }-.example-heading { margin-bottom: 0; }-.example-clear + .example-heading { margin-top: 0; padding-top: 0 }-.example-clear { clear: both }-.example .panel { padding: 1em; position: relative; }-.example .toggle {- background: #F40095;- color: white;- padding: 0.3em;- border-bottom-left-radius: 0.2em;- border-bottom-right-radius: 0.2em;- position: absolute;- top: -1px;- right: 1em;- font-size: 0.8em-}-.example .toggle-hide {- opacity: 0.5;- background: #eee;- color: #999;-}-.footer {- margin-top: 5em;- font-size: 0.9em;- background: #eee;- padding: 1em;- border-top-left-radius: 1em;- border-top-right-radius: 1em;-}-p code { background: #eee; padding: 0.1em 0.2em; }-.table-of-contents {- font-size: 0.9em;- border: #ddd;- background: #eee;- padding: 1em;- float: right;- border-radius: 5px;- margin-left: 1em;-}-.table-of-contents p {- padding: 0;- margin: 0;-}-.table-of-contents ul {- padding: 0;-}-.table-of-contents li {- list-style-type: none;-}-.table-of-contents .H2 {- margin-left: 1em;-}-.table-of-contents .H3 {- margin-left: 2em;-}-.table-of-contents a {- color: #555;-}
− docs/home.hs
@@ -1,230 +0,0 @@-{-# LANGUAGE EmptyDataDecls #-}---- | The home page script:------ 1) Make sure that the language samples are highlighted.--- 2) Add a show/hide button for the JS output on all samples.--- 3) For code samples that are too large, hide them.------ Because dogfood. This is not necessarily a good example, indeed, it--- may very well be a very bad example of how to write client--- code. But that's the point, really. Even the quick scripts that--- you'd just whip up in JS should be also done in Fay. Alright?-----module Home (main) where--import FFI-import Prelude---- | Main entry point.-main :: Fay ()-main = do- ready (wrap thedocument) $ do- indentAndHighlight- setupExpanders- setupTableOfContents---- | Setup highlighting/code re-indenting.-indentAndHighlight :: Fay ()-indentAndHighlight = do- samples <- query ".language-javascript"- each samples $ \i this ->- let sample = wrap this- in do text <- getText sample- setText sample (beautify text 2)- return True- setTabReplace hljs " "- initHighlightingOnLoad hljs---- | Setup example expanders.-setupExpanders :: Fay ()-setupExpanders = do- wrapwidth <- query ".wrap" >>= getWidth- examples <- query ".example"- each examples $ \i this -> do- tr <- getFind (wrap this) "tr"- left <- getFind tr "td" >>= getFirst- addClass left "left"- right <- getNext left- toggle <- makeElement "<a class='toggle' href='javascript:'>Show JavaScript</a>"- toggleButton <- return $ do- visible <- getIs right ":visible"- if visible- then do setText toggle "Hide JavaScript"- swapClasses toggle "toggle-hide" "toggle-show"- else do setText toggle "Show JavaScript"- swapClasses toggle "toggle-show" "toggle-hide"- setClick toggle $ fadeToggle right $ toggleButton- width <- getWidth tr- when (width > wrapwidth + 20*wrapwidth/100) $ hide right- toggleButton- panel <- getFind left ".panel"- prepend panel toggle- return True---- | Generate a table of contents.-setupTableOfContents :: Fay ()-setupTableOfContents = do- toc <- makeElement "<div class='table-of-contents'><p>Table of Contents</p></div>"- query ".subheadline" >>= after toc- ul <- makeElement "<ul></ul>" >>= appendTo toc- headings <- query "h2"- each headings $ \i heading ->- let anchor = ("section-" ++ show i)- h = wrap heading- in do -- Make sure the anchor exists at the heading point.- attr h "id" anchor- -- Make the entry.- li <- makeElement "<li></li>" >>= appendTo ul- a <- makeElement "<a></a>" >>= appendTo li- getText h >>= setText a- -- Link up to an anchor.- attr a "href" ("#" ++ anchor)- -- For the indentation.- getTagName heading >>= addClass li- return True------------------------------------------------------------------------------------- DOM--data Element-instance Foreign Element-instance Show Element---- | The document.-thedocument :: Element-thedocument = ffi "window.document"---- | Get the size of the given jquery array.-getTagName :: Element -> Fay String-getTagName = ffi "%1['tagName']"------------------------------------------------------------------------------------- jQuery--data JQuery-instance Foreign JQuery-instance Show JQuery---- | Make a jQuery object out of an element.-wrap :: Element -> JQuery-wrap = ffi "window['jQuery'](%1)"---- | Bind a handler for when the element is ready.-ready :: JQuery -> Fay () -> Fay ()-ready = ffi "%1['ready'](%2)"---- | Bind a handler for when the element is ready.-each :: JQuery -> (Double -> Element -> Fay Bool) -> Fay ()-each = ffi "%1['each'](%2)"---- | Query for elements.-query :: String -> Fay JQuery-query = ffi "window['jQuery'](%1)"---- | Set the text of the given object.-setText :: JQuery -> String -> Fay ()-setText = ffi "%1['text'](%2)"---- | Set the text of the given object.-attr :: JQuery -> String -> String -> Fay ()-attr = ffi "%1['attr'](%2,%3)"---- | Set the click of the given object.-setClick :: JQuery -> Fay () -> Fay ()-setClick = ffi "%1['click'](%2)"---- | Toggle the visibility of an element, faded.-fadeToggle :: JQuery -> Fay () -> Fay ()-fadeToggle = ffi "%1['fadeToggle'](%2)"---- | Hide an element.-hide :: JQuery -> Fay ()-hide = ffi "%1['hide']()"---- | Add a class to the given object.-addClass :: JQuery -> String -> Fay ()-addClass = ffi "%1['addClass'](%2)"---- | Remove a class from the given object.-removeClass :: JQuery -> String -> Fay ()-removeClass = ffi "%1['removeClass'](%2)"---- | Swap the given classes on the object.-swapClasses :: JQuery -> String -> String -> Fay ()-swapClasses obj addme removeme = do- addClass obj addme- removeClass obj removeme---- | Get the text of the given object.-getText :: JQuery -> Fay String-getText = ffi "%1['text']()"---- | Get the text of the given object.-getIs :: JQuery -> String -> Fay Bool-getIs = ffi "%1['is'](%2)"---- | Get the size of the given jquery array.-getSize :: JQuery -> Fay Double-getSize = ffi "%1['length']"---- | Get the next of the given object.-getNext :: JQuery -> Fay JQuery-getNext = ffi "%1['next']()"---- | Get the first of the given object.-getFirst :: JQuery -> Fay JQuery-getFirst = ffi "%1['first']()"---- | Get the find of the given object.-getFind :: JQuery -> String -> Fay JQuery-getFind = ffi "%1['find'](%2)"---- | Prepend an element to this one.-prepend :: JQuery -> JQuery -> Fay JQuery-prepend = ffi "%1['prepend'](%2)"---- | Append an element /after/ this one.-after :: JQuery -> JQuery -> Fay JQuery-after = ffi "%2['after'](%1)"---- | Append an element to this one.-append :: JQuery -> JQuery -> Fay JQuery-append = ffi "%1['append'](%2)"---- | Append this to an element.-appendTo :: JQuery -> JQuery -> Fay JQuery-appendTo = ffi "%2['appendTo'](%1)"---- | Make a new element.-makeElement :: String -> Fay JQuery-makeElement = ffi "window['jQuery'](%1)"---- | Get the width of the given object.-getWidth :: JQuery -> Fay Double-getWidth = ffi "%1['width']()"------------------------------------------------------------------------------------- Pretty printing / highlighting---- | Pretty print the given JS code.-beautify :: String -- ^ The JS code.- -> Double -- ^ The indentation level.- -> String -- ^ The reformatted JS code.-beautify = ffi "$jsBeautify(%1,%2)"--data Highlighter-instance Foreign Highlighter---- | Get the highlighter.-hljs :: Highlighter-hljs = ffi "window['hljs']"---- | Init syntax highlighting on load.-initHighlightingOnLoad :: Highlighter -> Fay ()-initHighlightingOnLoad = ffi "%1['initHighlightingOnLoad']()"---- | Init syntax highlighting on load.-setTabReplace :: Highlighter -> String -> Fay ()-setTabReplace = ffi "%1['tabReplace']=%2"
− docs/jquery.js
@@ -1,4 +0,0 @@-/*! jQuery v1.7.2 jquery.com | jquery.org/license */-(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"<!doctype html>":"")+"<html><body>"),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bD.test(a)?d(a,e):b_(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&f.type(b)==="object")for(var e in b)b_(a+"["+e+"]",b[e],c,d);else d(a,b)}function b$(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bZ(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bS,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bZ(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bZ(a,c,d,e,"*",g));return l}function bY(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bO),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bB(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?1:0,g=4;if(d>0){if(c!=="border")for(;e<g;e+=2)c||(d-=parseFloat(f.css(a,"padding"+bx[e]))||0),c==="margin"?d+=parseFloat(f.css(a,c+bx[e]))||0:d-=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0;return d+"px"}d=by(a,b);if(d<0||d==null)d=a.style[b];if(bt.test(d))return d;d=parseFloat(d)||0;if(c)for(;e<g;e+=2)d+=parseFloat(f.css(a,"padding"+bx[e]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+bx[e]))||0);return d+"px"}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;b.nodeType===1&&(b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?b.outerHTML=a.outerHTML:c!=="input"||a.type!=="checkbox"&&a.type!=="radio"?c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text):(a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value)),b.removeAttribute(f.expando),b.removeAttribute("_submit_attached"),b.removeAttribute("_change_attached"))}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c,i[c][d])}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h,i){var j,k=d==null,l=0,m=a.length;if(d&&typeof d=="object"){for(l in d)e.access(a,c,l,d[l],1,h,f);g=1}else if(f!==b){j=i===b&&e.isFunction(f),k&&(j?(j=c,c=function(a,b,c){return j.call(e(a),c)}):(c.call(a,f),c=null));if(c)for(;l<m;l++)c(a[l],d,j?f.call(a[l],l,c(a[l],d)):f,i);g=1}return g?a:k?c.call(a):m?c(a[0],d):h},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m,n=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?n(g):h==="function"&&(!a.unique||!p.has(g))&&c.push(g)},o=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,j=!0,m=k||0,k=0,l=c.length;for(;c&&m<l;m++)if(c[m].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}j=!1,c&&(a.once?e===!0?p.disable():c=[]:d&&d.length&&(e=d.shift(),p.fireWith(e[0],e[1])))},p={add:function(){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){j&&f<=l&&(l--,f<=m&&m--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&p.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(j?a.once||d.push([b,c]):(!a.once||!e)&&o(b,c));return this},fire:function(){p.fireWith(this,arguments);return this},fired:function(){return!!i}};return p};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p=c.createElement("div"),q=c.documentElement;p.setAttribute("className","t"),p.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="<div "+n+"display:block;'><div style='"+t+"0;display:block;overflow:hidden;'></div></div>"+"<table "+n+"' cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="<table><tr><td style='"+t+"0;display:none'></td><td>t</td></tr></table>",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="<div style='width:5px;'></div>",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h,i,j=this[0],k=0,m=null;if(a===b){if(this.length){m=f.data(j);if(j.nodeType===1&&!f._data(j,"parsedAttrs")){g=j.attributes;for(i=g.length;k<i;k++)h=g[k].name,h.indexOf("data-")===0&&(h=f.camelCase(h.substring(5)),l(j,h,m[h]));f._data(j,"parsedAttrs",!0)}}return m}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!";return f.access(this,function(c){if(c===b){m=this.triggerHandler("getData"+e,[d[0]]),m===b&&j&&(m=f.data(j,a),m=l(j,a,m));return m===b&&d[1]?this.data(d[0]):m}d[1]=c,this.each(function(){var b=f(this);b.triggerHandler("setData"+e,d),f.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length<d)return f.queue(this[0],a);return c===b?this:this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise(c)}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,f.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i<g;i++)e=d[i],e&&(c=f.propFix[e]||e,h=u.test(e),h||f.attr(a,e,""),a.removeAttribute(v?e:c),h&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0,coords:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(-a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:g&&G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=f.event.special[c.type]||{},j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(!i.preDispatch||i.preDispatch.call(this,c)!==!1){if(e&&(!c.button||c.type!=="click")){n=f(this),n.context=this.ownerDocument||this;for(m=c.target;m!=this;m=m.parentNode||this)if(m.disabled!==!0){p={},r=[],n[0]=m;for(k=0;k<e;k++)s=d[k],t=s.selector,p[t]===b&&(p[t]=s.quick?H(m,s.quick):n.is(t)),p[t]&&r.push(s);r.length&&j.push({elem:m,matches:r})}}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){q=j[k],c.currentTarget=q.elem;for(l=0;l<q.matches.length&&!c.isImmediatePropagationStopped();l++){s=q.matches[l];if(h||!c.namespace&&!s.namespace||c.namespace_re&&c.namespace_re.test(s.namespace))c.data=s.data,c.handleObj=s,o=((f.event.special[s.origType]||{}).handle||s.handler).apply(q.elem,g),o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()))}}i.postDispatch&&i.postDispatch.call(this,c);return c.result}},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),d._submit_attached=!0)})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9||d===11){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.globalPOS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")[\\s/>]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f-.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(f.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(g){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,function(a,b){b.src?f.ajax({type:"GET",global:!1,url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1></$2>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]==="<table>"&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)=="number")for(i=0;i<u;i++)bn(l[i]);else bn(l);l.nodeType?j.push(l):j=f.merge(j,l)}if(d){g=function(a){return!a.type||be.test(a.type)};for(k=0;j[k];k++){h=j[k];if(e&&f.nodeName(h,"script")&&(!h.type||be.test(h.type)))e.push(h.parentNode?h.parentNode.removeChild(h):h);else{if(h.nodeType===1){var v=f.grep(h.getElementsByTagName("script"),g);j.splice.apply(j,[k+1,0].concat(v))}d.appendChild(h)}}}return j},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bp=/alpha\([^)]*\)/i,bq=/opacity=([^)]*)/,br=/([A-Z]|^ms)/g,bs=/^[\-+]?(?:\d*\.)?\d+$/i,bt=/^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i,bu=/^([\-+])=([\-+.\de]+)/,bv=/^margin/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Top","Right","Bottom","Left"],by,bz,bA;f.fn.css=function(a,c){return f.access(this,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)},a,c,arguments.length>1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),(e===""&&f.css(d,"display")==="none"||!f.contains(d.ownerDocument.documentElement,d))&&f._data(d,"olddisplay",cu(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ct("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(ct("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o,p,q;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]);if((k=f.cssHooks[g])&&"expand"in k){l=k.expand(a[g]),delete a[g];for(i in l)i in a||(a[i]=l[i])}}for(g in a){h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cu(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cm.test(h)?(q=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),q?(f._data(this,"toggle"+i,q==="show"?"hide":"show"),j[q]()):j[h]()):(m=cn.exec(h),n=j.cur(),m?(o=parseFloat(m[2]),p=m[3]||(f.cssNumber[i]?"":"px"),p!=="px"&&(f.style(this,i,(o||1)+p),n=(o||1)/j.cur()*n,f.style(this,i,n+p)),m[1]&&(o=(m[1]==="-="?-1:1)*o+n),j.custom(n,o,p)):j.custom(n,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:ct("show",1),slideUp:ct("hide",1),slideToggle:ct("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a){return a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cq||cr(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){f._data(e.elem,"fxshow"+e.prop)===b&&(e.options.hide?f._data(e.elem,"fxshow"+e.prop,e.start):e.options.show&&f._data(e.elem,"fxshow"+e.prop,e.end))},h()&&f.timers.push(h)&&!co&&(co=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cq||cr(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(cp.concat.apply([],cp),function(a,b){b.indexOf("margin")&&(f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)})}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cv,cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?cv=function(a,b,c,d){try{d=a.getBoundingClientRect()}catch(e){}if(!d||!f.contains(c,a))return d?{top:d.top,left:d.left}:{top:0,left:0};var g=b.body,h=cy(b),i=c.clientTop||g.clientTop||0,j=c.clientLeft||g.clientLeft||0,k=h.pageYOffset||f.support.boxModel&&c.scrollTop||g.scrollTop,l=h.pageXOffset||f.support.boxModel&&c.scrollLeft||g.scrollLeft,m=d.top+k-i,n=d.left+l-j;return{top:m,left:n}}:cv=function(a,b,c){var d,e=a.offsetParent,g=a,h=b.body,i=b.defaultView,j=i?i.getComputedStyle(a,null):a.currentStyle,k=a.offsetTop,l=a.offsetLeft;while((a=a.parentNode)&&a!==h&&a!==c){if(f.support.fixedPosition&&j.position==="fixed")break;d=i?i.getComputedStyle(a,null):a.currentStyle,k-=a.scrollTop,l-=a.scrollLeft,a===e&&(k+=a.offsetTop,l+=a.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(a.nodeName))&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),g=e,e=a.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),j=d}if(j.position==="relative"||j.position==="static")k+=h.offsetTop,l+=h.offsetLeft;f.support.fixedPosition&&j.position==="fixed"&&(k+=Math.max(c.scrollTop,h.scrollTop),l+=Math.max(c.scrollLeft,h.scrollLeft));return{top:k,left:l}},f.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){f.offset.setOffset(this,a,b)});var c=this[0],d=c&&c.ownerDocument;if(!d)return null;if(c===d.body)return f.offset.bodyOffset(c);return cv(c,d,d.documentElement)},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
− docs/snippets/conditions.hs
@@ -1,9 +0,0 @@-number1 = if opposite then x else 6--number2 = if opposite- then x- else 6--number3 = case opposite of- True -> x- _ -> 6
− docs/snippets/data.hs
@@ -1,11 +0,0 @@-data Math = Math- { root :: Double -> Double- , square :: Double -> Double- , cube :: Double -> Double- }--math = Math sqrt- (\x -> x * x)- (\x -> x * square math x)--rootroot = root math (root math 5)
− docs/snippets/declarations.hs
@@ -1,5 +0,0 @@-number = 42--opposite = True--letbinding = let x = 42 in x
− docs/snippets/dom.hs
@@ -1,16 +0,0 @@-{-# LANGUAGE EmptyDataDecls #-}--main = do- result <- documentGetElements "body"- print result--print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" ""--data Element-instance Foreign Element--documentGetElements :: String -> Fay [Element]-documentGetElements =- foreignFay "document.getElementsByTagName"- "array"
− docs/snippets/enums.hs
@@ -1,18 +0,0 @@-data Role = CEO- | Manager- | Developer- | Marketing--data Customer = Customer- { cid :: Double- , address :: String- , role :: Role- }--monthlySalary :: Customer -> Double-monthlySalary customer =- case role customer of- CEO -> 1000000- Manager -> 100000- Marketing -> 1000- Developer -> 1
− docs/snippets/ffi.hs
@@ -1,17 +0,0 @@-print :: Foreign a => a -> Fay ()-print = ffi "window.console.log(%1)"--alert :: Foreign a => a -> Fay ()-alert = ffi "window.alert(%1)"--getInnerHtml :: Element -> Fay String-getInnerHtml = ffi "%1.innerHTML"--setInnerHtml :: Element -> String -> Fay ()-setInnerHtml = ffi "%1.innerHTML=%2"--thedocument :: Element-thedocument = ffi "window.document"--jquery :: Element -> JQuery-jquery = ffi "window.jQuery(%1)"
− docs/snippets/functions.hs
@@ -1,3 +0,0 @@-square x = x * x--add = \x -> x + x
− docs/snippets/lists.hs
@@ -1,9 +0,0 @@-list1 = [1,2,3,4,5]--list2 = [1..5]--list3 = [1..]--one = head list1--squared = map square list1
− docs/snippets/patterns.hs
@@ -1,11 +0,0 @@-data Math = Math- { root :: Double -> Double- , square :: Double -> Double- , cube :: Double -> Double- }--race (winner,runners) = print (winner,runners)--first (x:xs) = x--getSquare (Math _ square _) = square
− docs/snippets/tail.hs
@@ -1,4 +0,0 @@--- Tail-recursive functions will use--- constant stack space-sum 0 acc = acc-sum n acc = sum (n - 1) (acc + n)
examples/alert.hs view
@@ -2,8 +2,8 @@ module Alert where -import Language.Fay.FFI-import Language.Fay.Prelude+import FFI+import Prelude main :: Fay () main = alert "Hello, World!"
examples/canvaswater.hs view
@@ -8,8 +8,8 @@ module CanvasWater (main) where -import Language.Fay.FFI-import Language.Fay.Prelude+import FFI+import Prelude -- | Main entry point. main :: Fay ()
examples/console.hs view
@@ -1,5 +1,13 @@-module Console where+module Console (main) where import Prelude+import FFI -main = putStrLn "Hello, World!"+main = putStrLn (showInt (fib 10))++fib 0 = 0+fib 1 = 1+fib n = fib (n - 1) + fib (n - 2)++showInt :: Int -> String+showInt = ffi "%1+''"
examples/data.hs view
@@ -8,8 +8,8 @@ module Data where -import Language.Fay.FFI-import Language.Fay.Prelude+import FFI+import Prelude data Foo = Foo { x :: Double, y :: String, z :: Foo } | Bar deriving (Show)
examples/dom.hs view
@@ -3,8 +3,8 @@ module Dom where -import Language.Fay.FFI-import Language.Fay.Prelude+import FFI+import Prelude main :: Fay () main = addEventListener "load" printBody False
examples/ref.hs view
@@ -5,8 +5,8 @@ module Ref where -import Language.Fay.FFI-import Language.Fay.Prelude+import FFI+import Prelude main :: Fay () main = do
examples/tailrecursive.hs view
@@ -8,8 +8,8 @@ module Tailrecursive where -import Language.Fay.FFI-import Language.Fay.Prelude+import FFI+import Prelude main = do benchmark $ printI (map (\x -> x+1) fibs !! 10)
fay.cabal view
@@ -1,5 +1,5 @@ name: fay-version: 0.12.0.1+version: 0.14.0.0 synopsis: A compiler for Fay, a Haskell subset that compiles to JavaScript. description: Fay is a proper subset of Haskell which is type-checked with GHC, and compiled to JavaScript. It is lazy, pure, has a Fay monad,@@ -13,7 +13,6 @@ > $ cd fay-* > $ cabal install > $ cabal install fay-base- > $ dist/build/fay-docs/fay-docs . . /Examples/@@ -22,32 +21,38 @@ . /Release Notes/ .- . * Updates to name resolution.+ * Update test-cases for serialization. .- . * Added initial fay-base support.+ * ce7a34a Fix fully specified parametrized type serialization. .- . * Basic CPP support (#136)+ * Full documentation. .- . * Serialization of Text values (#136)+ * Change Language.Fay.* to Fay.*. .- . * Add Automatic serialization, export Automatic/Ptr, bump version.+ * Resolve packages using dataDir. .- . * Do not automatically serialize polymorphic values.+ * Optimize FFI for embedded scripts. .- . * Support Ptr type to force the serializer to ignore things.+ * Option to not export built-ins. .- . * Add very dubious --package flag.+ * Flag to export only stdout. .- . * Support type imports (IAbs)+ * Output source of runtime rather than filename. .- . * Support import X (a, b) and import X hiding (a, b).+ * Flag to output only the serialization dispatcher. .- . * Implement guards in case branches+ * Flag to exclude the serialization dispatcher. .- . * Fix instance declarations missing when typechecking (closes #177)+ * Flag to exclude stdlib from output. .- . * Bump optparse-applicative to >= 0.5 (closes #195)+ * Flag to output naked decls (unwrapped). .+ * Flag to print out the runtime JS source.+ .+ * Flag to not export runtime.+ .+ * Remove Language.Fay.Stdlib/Prelude, superseded by fay-base+ . See full history at: <https://github.com/faylang/fay/commits> homepage: http://fay-lang.org/ bug-reports: https://github.com/faylang/fay/issues@@ -61,7 +66,6 @@ cabal-version: >=1.8 data-files: js/runtime.js hs/stdlib.hs- src/Language/Fay/Stdlib.hs src/Language/Fay/FFI.hs extra-source-files: examples/ref.hs examples/alert.hs examples/console.hs examples/dom.hs examples/tailrecursive.hs examples/data.hs examples/canvaswater.hs@@ -106,51 +110,36 @@ tests/Hierarchical/Export.hs tests/Hierarchical/RecordDefined.hs tests/Api/Records.hs tests/Api/ImportRecords.hs- -- Documentation files- docs/beautify.js docs/highlight.pack.js docs/home.css docs/jquery.js- docs/analytics.js- -- Documentation snippets- docs/snippets/conditions.hs- docs/snippets/data.hs- docs/snippets/declarations.hs- docs/snippets/dom.hs- docs/snippets/enums.hs- docs/snippets/ffi.hs- docs/snippets/functions.hs- docs/snippets/lists.hs- docs/snippets/patterns.hs- docs/snippets/tail.hs- docs/home.hs+ tests/Api/CPPTypecheck.hs+ tests/serialization.hs tests/serialization source-repository head type: git location: https://github.com/faylang/fay.git Flag devel- Description: Don't build fay-tests and fay-docs if this flag is supplied+ Description: Don't build fay-tests if this flag is supplied Default: False library hs-source-dirs: src- exposed-modules: Language.Fay, Language.Fay.Types, Language.Fay.FFI, Language.Fay.Prelude, Language.Fay.Convert, Language.Fay.Compiler, Language.Fay.Compiler.Misc, Language.Fay.Compiler.FFI, Language.Fay.Compiler.Optimizer, Language.Fay.Compiler.Packages, Language.Fay.ModuleScope- other-modules: Language.Fay.Print, Control.Monad.IO, Language.Fay.Stdlib, System.Process.Extra, Data.List.Extra, Paths_fay- ghc-options: -O2 -Wall+ exposed-modules: Fay, Fay.Types, Language.Fay.FFI, Fay.Convert, Fay.Compiler, Fay.Compiler.Debug, Fay.Compiler.Config+ other-modules: Fay.Compiler.Print, Control.Monad.IO, System.Process.Extra, Data.List.Extra, Paths_fay, Fay.Compiler.Misc, Fay.Compiler.FFI, Fay.Compiler.Optimizer, Fay.Compiler.Packages, Fay.Compiler.ModuleScope, Control.Monad.Extra, Fay.Compiler.CollectRecords, Fay.Compiler.Decl, Fay.Compiler.Defaults, Fay.Compiler.Exp, Fay.Compiler.Pattern, Fay.Compiler.Typecheck+ ghc-options: -O2 -Wall -fno-warn-name-shadowing build-depends: base >= 4 && < 5, aeson, attoparsec,- bytestring, containers, data-default, directory, filepath, ghc-paths,- groom,+ Cabal, haskell-src-exts, language-ecmascript >= 0.10, mtl, pretty-show, process,- random, safe, syb, text,@@ -180,26 +169,19 @@ main-is: Main.hs build-depends: base >= 4 && < 5, aeson,- attoparsec,- bytestring, containers, data-default, directory, filepath, ghc-paths,- groom,+ Cabal, haskell-src-exts, language-ecmascript >= 0.10, mtl,- pretty-show, process,- random, safe, syb,- text,- unordered-containers, utf8-string,- vector, haskeline, optparse-applicative >= 0.5,@@ -212,7 +194,7 @@ ghc-options: -O2 -Wall -threaded -with-rtsopts=-N ghc-prof-options: -fprof-auto main-is: Tests.hs- other-modules: Language.Fay.Compiler Test.Convert Test.Api Test.CommandLine Test.Util+ other-modules: Fay.Compiler Test.Convert Test.Api Test.CommandLine Test.Util build-depends: base >= 4 && < 5, aeson, attoparsec,@@ -222,13 +204,12 @@ directory, filepath, ghc-paths,- groom,+ Cabal, haskell-src-exts, language-ecmascript >= 0.10, mtl, pretty-show, process,- random, safe, syb, text,@@ -240,38 +221,3 @@ test-framework, test-framework-hunit, test-framework-th--executable fay-docs- if flag(devel)- buildable: False- hs-source-dirs: src- ghc-options: -O2 -Wall- main-is: Docs.hs- other-modules: Text.Blaze.Extra- build-depends: base >= 4 && < 5,- aeson,- attoparsec,- bytestring,- containers,- data-default,- directory,- filepath,- ghc-paths,- groom,- haskell-src-exts,- language-ecmascript >= 0.10,- mtl,- pretty-show,- process,- random,- safe,- syb,- text,- time,- unordered-containers,- utf8-string,- vector,-- HUnit,- blaze-html >= 0.5,- blaze-markup
js/runtime.js view
@@ -1,35 +1,32 @@-var True = true;-var False = false;- /******************************************************************************* * Thunks. */ // Force a thunk (if it is a thunk) until WHNF.-function _(thunkish,nocache){- while (thunkish instanceof $) {+function Fay$$_(thunkish,nocache){+ while (thunkish instanceof Fay$$$) { thunkish = thunkish.force(nocache); } return thunkish; } // Apply a function to arguments (see method2 in Fay.hs).-function __(){+function Fay$$__(){ var f = arguments[0]; for (var i = 1, len = arguments.length; i < len; i++) {- f = (f instanceof $? _(f) : f)(arguments[i]);+ f = (f instanceof Fay$$$? Fay$$_(f) : f)(arguments[i]); } return f; } // Thunk object.-function $(value){+function Fay$$$(value){ this.forced = false; this.value = value; } // Force the thunk.-$.prototype.force = function(nocache) {+Fay$$$.prototype.force = function(nocache) { return nocache ? this.value() : (this.forced ?@@ -40,13 +37,13 @@ function Fay$$seq(x) { return function(y) {- _(x,false);+ Fay$$_(x,false); return y; } } function Fay$$seq$36$uncurried(x,y) {- _(x,false);+ Fay$$_(x,false); return y; } @@ -78,9 +75,9 @@ // This is used directly from Fay, but can be rebound or shadowed. See primOps in Types.hs. function Fay$$bind(m){ return function(f){- return new $(function(){- var monad = _(m,true);- return _(f)(monad.value);+ return new Fay$$$(function(){+ var monad = Fay$$_(m,true);+ return Fay$$_(f)(monad.value); }); }; }@@ -88,10 +85,10 @@ // >>= // This is used directly from Fay, but can be rebound or shadowed. See primOps in Types.hs. function Fay$$bind$36$uncurried(m,f){- return new $(function(){- var monad = _(m,true);- return _(f)(monad.value);- });+ return new Fay$$$(function(){+ var monad = Fay$$_(m,true);+ return Fay$$_(f)(monad.value);+ }); } // This is used directly from Fay, but can be rebound or shadowed.@@ -102,8 +99,8 @@ // Allow the programmer to access thunk forcing directly. function Fay$$force(thunk){ return function(type){- return new $(function(){- _(thunk,type);+ return new Fay$$$(function(){+ Fay$$_(thunk,type); return new Fay$$Monad(Fay$$unit); }) }@@ -127,222 +124,208 @@ var base = type[0]; var args = type[1]; var jsObj;- switch(base){- case "ptr": {- jsObj = fayObj;- break;- }- case "action": {- // A nullary monadic action. Should become a nullary JS function.- // Fay () -> function(){ return ... }- jsObj = function(){- return Fay$$fayToJs(args[0],_(fayObj,true).value);- };- break;- }- case "function": {- // A proper function.- jsObj = function(){- var fayFunc = fayObj;- var return_type = args[args.length-1];- var len = args.length;- // If some arguments.- if (len > 1) {- // Apply to all the arguments.- fayFunc = _(fayFunc,true);- // TODO: Perhaps we should throw an error when JS- // passes more arguments than Haskell accepts.- for (var i = 0, len = len; i < len - 1 && fayFunc instanceof Function; i++) {- // Unserialize the JS values to Fay for the Fay callback.- fayFunc = _(fayFunc(Fay$$jsToFay(args[i],arguments[i])),true);- }- // Finally, serialize the Fay return value back to JS.- var return_base = return_type[0];- var return_args = return_type[1];- // If it's a monadic return value, get the value instead.- if(return_base == "action") {- return Fay$$fayToJs(return_args[0],fayFunc.value);- }- // Otherwise just serialize the value direct.- else {- return Fay$$fayToJs(return_type,fayFunc);- }- } else {- throw new Error("Nullary function?");+ if(base == "action") {+ // A nullary monadic action. Should become a nullary JS function.+ // Fay () -> function(){ return ... }+ jsObj = function(){+ return Fay$$fayToJs(args[0],Fay$$_(fayObj,true).value);+ };++ }+ else if(base == "function") {+ // A proper function.+ jsObj = function(){+ var fayFunc = fayObj;+ var return_type = args[args.length-1];+ var len = args.length;+ // If some arguments.+ if (len > 1) {+ // Apply to all the arguments.+ fayFunc = Fay$$_(fayFunc,true);+ // TODO: Perhaps we should throw an error when JS+ // passes more arguments than Haskell accepts.+ for (var i = 0, len = len; i < len - 1 && fayFunc instanceof Function; i++) {+ // Unserialize the JS values to Fay for the Fay callback.+ fayFunc = Fay$$_(fayFunc(Fay$$jsToFay(args[i],arguments[i])),true); }- };- break;- }- case "string": {- // Serialize Fay string to JavaScript string.- var str = "";- fayObj = _(fayObj);- while(fayObj instanceof Fay$$Cons) {- str += fayObj.car;- fayObj = _(fayObj.cdr);- }- jsObj = str;- break;- }- case "list": {- // Serialize Fay list to JavaScript array.- var arr = [];- fayObj = _(fayObj);- while(fayObj instanceof Fay$$Cons) {- arr.push(Fay$$fayToJs(args[0],fayObj.car));- fayObj = _(fayObj.cdr);- }- jsObj = arr;- break;- }- case "tuple": {- // Serialize Fay tuple to JavaScript array.- var arr = [];- fayObj = _(fayObj);- var i = 0;- while(fayObj instanceof Fay$$Cons) {- arr.push(Fay$$fayToJs(args[i++],fayObj.car));- fayObj = _(fayObj.cdr);- }- jsObj = arr;- break;- }- case "defined": {- fayObj = _(fayObj);- if (fayObj instanceof $_Language$Fay$FFI$Undefined) {- jsObj = undefined;- } else {- jsObj = Fay$$fayToJsUserDefined(args[0],fayObj["slot1"]);- }- break;- }- case "nullable": {- fayObj = _(fayObj);- if (fayObj instanceof $_Language$Fay$FFI$Null) {- jsObj = null;+ // Finally, serialize the Fay return value back to JS.+ var return_base = return_type[0];+ var return_args = return_type[1];+ // If it's a monadic return value, get the value instead.+ if(return_base == "action") {+ return Fay$$fayToJs(return_args[0],fayFunc.value);+ }+ // Otherwise just serialize the value direct.+ else {+ return Fay$$fayToJs(return_type,fayFunc);+ } } else {- jsObj = Fay$$fayToJsUserDefined(args[0],fayObj["slot1"]);+ throw new Error("Nullary function?"); }- break;- }- case "double": {- // Serialize double, just force the argument. Doubles are unboxed.- jsObj = _(fayObj);- break;- }- case "int": {- // Serialize int, just force the argument. Ints are unboxed.- jsObj = _(fayObj);- break;+ };++ }+ else if(base == "string") {+ jsObj = Fay$$fayToJs_string(fayObj);+ }+ else if(base == "list") {+ // Serialize Fay list to JavaScript array.+ var arr = [];+ fayObj = Fay$$_(fayObj);+ while(fayObj instanceof Fay$$Cons) {+ arr.push(Fay$$fayToJs(args[0],fayObj.car));+ fayObj = Fay$$_(fayObj.cdr); }- case "bool": {- // Bools are unboxed.- jsObj = _(fayObj);- break;+ jsObj = arr;++ }+ else if(base == "tuple") {+ // Serialize Fay tuple to JavaScript array.+ var arr = [];+ fayObj = Fay$$_(fayObj);+ var i = 0;+ while(fayObj instanceof Fay$$Cons) {+ arr.push(Fay$$fayToJs(args[i++],fayObj.car));+ fayObj = Fay$$_(fayObj.cdr); }- case "unknown":- return fayObj;- case "automatic":- case "user": {- if(fayObj instanceof $)- fayObj = _(fayObj);- jsObj = Fay$$fayToJsUserDefined(type,fayObj);- break;+ jsObj = arr;++ }+ else if(base == "defined") {+ fayObj = Fay$$_(fayObj);+ if (fayObj instanceof $_Language$Fay$FFI$Undefined) {+ jsObj = undefined;+ } else {+ jsObj = Fay$$fayToJsUserDefined(args[0],fayObj["slot1"]); }- default: throw new Error("Unhandled Fay->JS translation type: " + base);++ }+ else if(base == "nullable") {+ fayObj = Fay$$_(fayObj);+ if (fayObj instanceof $_Language$Fay$FFI$Null) {+ jsObj = null;+ } else {+ jsObj = Fay$$fayToJsUserDefined(args[0],fayObj["slot1"]); }- return jsObj;++ }+ else if(base == "double" || base == "int" || base == "bool") {+ // Bools are unboxed.+ jsObj = Fay$$_(fayObj);++ }+ else if(base == "ptr" || base == "unknown")+ return fayObj;+ else if(base == "automatic" || base == "user") {+ if(fayObj instanceof Fay$$$)+ fayObj = Fay$$_(fayObj);+ jsObj = Fay$$fayToJsUserDefined(type,fayObj);++ }+ else+ throw new Error("Unhandled Fay->JS translation type: " + base);+ return jsObj; } +// Specialized serializer for string.+function Fay$$fayToJs_string(fayObj){+ // Serialize Fay string to JavaScript string.+ var str = "";+ fayObj = Fay$$_(fayObj);+ while(fayObj instanceof Fay$$Cons) {+ str += fayObj.car;+ fayObj = Fay$$_(fayObj.cdr);+ }+ return str;+};+function Fay$$jsToFay_string(x){+ return Fay$$list(x)+};++// Special num/bool serializers.+function Fay$$jsToFay_int(x){return x;}+function Fay$$jsToFay_double(x){return x;}+function Fay$$jsToFay_bool(x){return x;}++function Fay$$fayToJs_int(x){return Fay$$_(x);}+function Fay$$fayToJs_double(x){return Fay$$_(x);}+function Fay$$fayToJs_bool(x){return Fay$$_(x);}+ // Unserialize an object from JS to Fay. function Fay$$jsToFay(type,jsObj){ var base = type[0]; var args = type[1]; var fayObj;- switch(base){- case "ptr": {- fayObj = jsObj;- break;- }- case "action": {- // Unserialize a "monadic" JavaScript return value into a monadic value.- fayObj = new Fay$$Monad(Fay$$jsToFay(args[0],jsObj));- break;- }- case "string": {- // Unserialize a JS string into Fay list (String).- fayObj = Fay$$list(jsObj);- break;- }- case "list": {- // Unserialize a JS array into a Fay list ([a]).- var serializedList = [];- for (var i = 0, len = jsObj.length; i < len; i++) {- // Unserialize each JS value into a Fay value, too.- serializedList.push(Fay$$jsToFay(args[0],jsObj[i]));- }- // Pop it all in a Fay list.- fayObj = Fay$$list(serializedList);- break;- }- case "tuple": {- // Unserialize a JS array into a Fay tuple ((a,b,c,...)).- var serializedTuple = [];- for (var i = 0, len = jsObj.length; i < len; i++) {- // Unserialize each JS value into a Fay value, too.- serializedTuple.push(Fay$$jsToFay(args[i],jsObj[i]));- }- // Pop it all in a Fay list.- fayObj = Fay$$list(serializedTuple);- break;+ if(base == "action") {+ // Unserialize a "monadic" JavaScript return value into a monadic value.+ fayObj = new Fay$$Monad(Fay$$jsToFay(args[0],jsObj));++ }+ else if(base == "string") {+ // Unserialize a JS string into Fay list (String).+ fayObj = Fay$$list(jsObj);+ }+ else if(base == "list") {+ // Unserialize a JS array into a Fay list ([a]).+ var serializedList = [];+ for (var i = 0, len = jsObj.length; i < len; i++) {+ // Unserialize each JS value into a Fay value, too.+ serializedList.push(Fay$$jsToFay(args[0],jsObj[i])); }- case "defined": {- if (jsObj === undefined) {- fayObj = new $_Language$Fay$FFI$Undefined();- } else {- fayObj = new $_Language$Fay$FFI$Defined(Fay$$jsToFay(args[0],jsObj));- }- break;+ // Pop it all in a Fay list.+ fayObj = Fay$$list(serializedList);++ }+ else if(base == "tuple") {+ // Unserialize a JS array into a Fay tuple ((a,b,c,...)).+ var serializedTuple = [];+ for (var i = 0, len = jsObj.length; i < len; i++) {+ // Unserialize each JS value into a Fay value, too.+ serializedTuple.push(Fay$$jsToFay(args[i],jsObj[i])); }- case "nullable": {- if (jsObj === null) {- fayObj = new $_Language$Fay$FFI$Null();- } else {- fayObj = new $_Language$Fay$FFI$Nullable(Fay$$jsToFay(args[0],jsObj));- }- break;+ // Pop it all in a Fay list.+ fayObj = Fay$$list(serializedTuple);++ }+ else if(base == "defined") {+ if (jsObj === undefined) {+ fayObj = new $_Language$Fay$FFI$Undefined();+ } else {+ fayObj = new $_Language$Fay$FFI$Defined(Fay$$jsToFay(args[0],jsObj)); }- case "double": {- // Doubles are unboxed, so there's nothing to do.- fayObj = jsObj;- break;++ }+ else if(base == "nullable") {+ if (jsObj === null) {+ fayObj = new $_Language$Fay$FFI$Null();+ } else {+ fayObj = new $_Language$Fay$FFI$Nullable(Fay$$jsToFay(args[0],jsObj)); }- case "int": {- // Int are unboxed, so there's no forcing to do.- // But we can do validation that the int has no decimal places.- // E.g. Math.round(x)!=x? throw "NOT AN INTEGER, GET OUT!"- fayObj = Math.round(jsObj);- if(fayObj!==jsObj) throw "Argument " + jsObj + " is not an integer!";- break;++ }+ else if(base == "int") {+ // Int are unboxed, so there's no forcing to do.+ // But we can do validation that the int has no decimal places.+ // E.g. Math.round(x)!=x? throw "NOT AN INTEGER, GET OUT!"+ fayObj = Math.round(jsObj);+ if(fayObj!==jsObj) throw "Argument " + jsObj + " is not an integer!";++ }+ else if (base == "double" ||+ base == "bool" ||+ base == "ptr" ||+ base == "unknown") {+ return jsObj;+ }+ else if(base == "automatic" || base == "user") {+ if (jsObj && jsObj['instance']) {+ fayObj = Fay$$jsToFayUserDefined(type,jsObj); }- case "bool": {- // Bools are unboxed.+ else fayObj = jsObj;- break;- }- case "unknown":- return jsObj;- case "automatic":- case "user": {- if (jsObj && jsObj['instance']) {- fayObj = Fay$$jsToFayUserDefined(type,jsObj);- }- else- fayObj = jsObj;- break;- }- default: throw new Error("Unhandled JS->Fay translation type: " + base);+ }+ else { throw new Error("Unhandled JS->Fay translation type: " + base); } return fayObj; } @@ -376,7 +359,7 @@ // `list' cannot be null and `index' cannot be out of bounds. function Fay$$index(index,list){ for(var i = 0; i < index; i++) {- list = _(list.cdr);+ list = Fay$$_(list.cdr); } return list.car; }@@ -385,7 +368,7 @@ // `list' is already forced by the time it's passed to this function. function Fay$$listLen(list,max){ for(var i = 0; list !== null && i < max + 1; i++) {- list = _(list.cdr);+ list = Fay$$_(list.cdr); } return i == max; }@@ -397,25 +380,25 @@ // Built-in *. function Fay$$mult(x){ return function(y){- return new $(function(){- return _(x) * _(y);+ return new Fay$$$(function(){+ return Fay$$_(x) * Fay$$_(y); }); }; } function Fay$$mult$36$uncurried(x,y){ - return new $(function(){- return _(x) * _(y);- });+ return new Fay$$$(function(){+ return Fay$$_(x) * Fay$$_(y);+ }); } // Built-in +. function Fay$$add(x){ return function(y){- return new $(function(){- return _(x) + _(y);+ return new Fay$$$(function(){+ return Fay$$_(x) + Fay$$_(y); }); }; }@@ -423,44 +406,44 @@ // Built-in +. function Fay$$add$36$uncurried(x,y){ - return new $(function(){- return _(x) + _(y);- });+ return new Fay$$$(function(){+ return Fay$$_(x) + Fay$$_(y);+ }); } // Built-in -. function Fay$$sub(x){ return function(y){- return new $(function(){- return _(x) - _(y);+ return new Fay$$$(function(){+ return Fay$$_(x) - Fay$$_(y); }); }; } // Built-in -. function Fay$$sub$36$uncurried(x,y){ - return new $(function(){- return _(x) - _(y);- });+ return new Fay$$$(function(){+ return Fay$$_(x) - Fay$$_(y);+ }); } // Built-in /.-function Fay$$div(x){+function Fay$$divi(x){ return function(y){- return new $(function(){- return _(x) / _(y);+ return new Fay$$$(function(){+ return Fay$$_(x) / Fay$$_(y); }); }; } // Built-in /.-function Fay$$div$36$uncurried(x,y){+function Fay$$divi$36$uncurried(x,y){ - return new $(function(){- return _(x) / _(y);- });+ return new Fay$$$(function(){+ return Fay$$_(x) / Fay$$_(y);+ }); } @@ -471,8 +454,8 @@ // Are two values equal? function Fay$$equal(lit1, lit2) { // Simple case- lit1 = _(lit1);- lit2 = _(lit2);+ lit1 = Fay$$_(lit1);+ lit2 = Fay$$_(lit2); if (lit1 === lit2) { return true; }@@ -487,7 +470,7 @@ do { if (!Fay$$equal(lit1.car,lit2.car)) return false;- lit1 = _(lit1.cdr), lit2 = _(lit2.cdr);+ lit1 = Fay$$_(lit1.cdr), lit2 = Fay$$_(lit2.cdr); if (lit1 === null || lit2 === null) return lit1 === lit2; } while (true);@@ -507,7 +490,7 @@ // Built-in ==. function Fay$$eq(x){ return function(y){- return new $(function(){+ return new Fay$$$(function(){ return Fay$$equal(x,y); }); };@@ -515,16 +498,16 @@ function Fay$$eq$36$uncurried(x,y){ - return new $(function(){- return Fay$$equal(x,y);- });+ return new Fay$$$(function(){+ return Fay$$equal(x,y);+ }); } // Built-in /=. function Fay$$neq(x){ return function(y){- return new $(function(){+ return new Fay$$$(function(){ return !(Fay$$equal(x,y)); }); };@@ -533,17 +516,17 @@ // Built-in /=. function Fay$$neq$36$uncurried(x,y){ - return new $(function(){- return !(Fay$$equal(x,y));- });+ return new Fay$$$(function(){+ return !(Fay$$equal(x,y));+ }); } // Built-in >. function Fay$$gt(x){ return function(y){- return new $(function(){- return _(x) > _(y);+ return new Fay$$$(function(){+ return Fay$$_(x) > Fay$$_(y); }); }; }@@ -551,17 +534,17 @@ // Built-in >. function Fay$$gt$36$uncurried(x,y){ - return new $(function(){- return _(x) > _(y);- });+ return new Fay$$$(function(){+ return Fay$$_(x) > Fay$$_(y);+ }); } // Built-in <. function Fay$$lt(x){ return function(y){- return new $(function(){- return _(x) < _(y);+ return new Fay$$$(function(){+ return Fay$$_(x) < Fay$$_(y); }); }; }@@ -570,9 +553,9 @@ // Built-in <. function Fay$$lt$36$uncurried(x,y){ - return new $(function(){- return _(x) < _(y);- });+ return new Fay$$$(function(){+ return Fay$$_(x) < Fay$$_(y);+ }); } @@ -580,8 +563,8 @@ // Built-in >=. function Fay$$gte(x){ return function(y){- return new $(function(){- return _(x) >= _(y);+ return new Fay$$$(function(){+ return Fay$$_(x) >= Fay$$_(y); }); }; }@@ -589,17 +572,17 @@ // Built-in >=. function Fay$$gte$36$uncurried(x,y){ - return new $(function(){- return _(x) >= _(y);- });+ return new Fay$$$(function(){+ return Fay$$_(x) >= Fay$$_(y);+ }); } // Built-in <=. function Fay$$lte(x){ return function(y){- return new $(function(){- return _(x) <= _(y);+ return new Fay$$$(function(){+ return Fay$$_(x) <= Fay$$_(y); }); }; }@@ -607,17 +590,17 @@ // Built-in <=. function Fay$$lte$36$uncurried(x,y){ - return new $(function(){- return _(x) <= _(y);- });+ return new Fay$$$(function(){+ return Fay$$_(x) <= Fay$$_(y);+ }); } // Built-in &&. function Fay$$and(x){ return function(y){- return new $(function(){- return _(x) && _(y);+ return new Fay$$$(function(){+ return Fay$$_(x) && Fay$$_(y); }); }; }@@ -625,17 +608,17 @@ // Built-in &&. function Fay$$and$36$uncurried(x,y){ - return new $(function(){- return _(x) && _(y);- });- ;+ return new Fay$$$(function(){+ return Fay$$_(x) && Fay$$_(y);+ });+ ; } // Built-in ||. function Fay$$or(x){ return function(y){- return new $(function(){- return _(x) || _(y);+ return new Fay$$$(function(){+ return Fay$$_(x) || Fay$$_(y); }); }; }@@ -643,9 +626,9 @@ // Built-in ||. function Fay$$or$36$uncurried(x,y){ - return new $(function(){- return _(x) || _(y);- });+ return new Fay$$$(function(){+ return Fay$$_(x) || Fay$$_(y);+ }); }
+ src/Control/Monad/Extra.hs view
@@ -0,0 +1,31 @@+-- | Extra monadic functions.++module Control.Monad.Extra where++import Control.Monad+import Data.Maybe++-- | Word version of flip (>>=).+bind :: (Monad m) => (a -> m b) -> m a -> m b+bind = flip (>>=)++-- | When the value is Just.+whenJust :: Monad m => Maybe a -> (a -> m ()) -> m ()+whenJust (Just a) m = m a+whenJust Nothing _ = return ()++-- | Wrap up a form in a Maybe.+just :: Functor m => m a -> m (Maybe a)+just = fmap Just++-- | Flip of mapMaybe.+forMaybe :: [a] -> (a -> Maybe b) -> [b]+forMaybe = flip mapMaybe++-- | Monadic version of maybe.+maybeM :: (Monad m) => a -> (a1 -> m a) -> Maybe a1 -> m a+maybeM nil cons a = maybe (return nil) cons a++-- | Do any of the (monadic) predicates match?+anyM :: Monad m => (a -> m Bool) -> [a] -> m Bool+anyM p l = return . not . null =<< filterM p l
src/Control/Monad/IO.hs view
@@ -1,6 +1,9 @@+-- | Alias of MonadIO.+ module Control.Monad.IO where import Control.Monad.Trans +-- | Alias of liftIO, I hate typing it. Hate reading it. io :: MonadIO m => IO a -> m a io = liftIO
src/Data/List/Extra.hs view
@@ -1,10 +1,14 @@+-- | Extra list functions.+ module Data.List.Extra where import Data.List hiding (map) import Prelude hiding (map) +-- | Get the union of a list of lists. unionOf :: (Eq a) => [[a]] -> [a] unionOf = foldr union [] +-- | Flip of map. for :: (Functor f) => f a -> (a -> b) -> f b for = flip fmap
− src/Docs.hs
@@ -1,320 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}-{-# OPTIONS -fno-warn-missing-signatures -fno-warn-unused-do-bind #-}---- | Generate documentation for Fay.--module Main where--import Control.Monad-import qualified Data.ByteString.Lazy as L-import Data.Char-import Data.Default-import Data.Time-import Language.Fay (compileFromTo)-import Language.Fay.Compiler (compileForDocs, compileViaStr)-import Language.Fay.Types (CompileConfig (..),- PrintState (..))--import Prelude hiding (div, head)-import System.FilePath-import Text.Blaze.Extra-import System.Environment-import Text.Blaze.Html5 as H hiding (contents, map, style)-import Text.Blaze.Html5.Attributes as A hiding (title)-import Text.Blaze.Renderer.Utf8 (renderMarkup)----- | Main entry point.-main :: IO ()-main = do- let file = "docs" </> "index.html"- generate >>= L.writeFile file- generateJs- putStrLn $ "Documentation file written to " ++ file--generate = do- sources <- mapM readFile examples- javascripts <- mapM compile examples- now <- getCurrentTime- analytics <- readFile $ "docs" </> "analytics.js"- return $ renderMarkup $ page now- analytics- (zip3 (map titlize examples) sources javascripts)-- where compile file = do- contents <- readFile file- putStrLn $ "Generating " ++ file ++ " ..."- packageConf <- fmap (lookup "HASKELL_PACKAGE_SANDBOX") getEnvironment- result <- compileViaStr file- def { configFlattenApps = True- , configOptimize = True- , configTypecheck = False- , configPackageConf = packageConf- }- compileForDocs contents- case result of- Right (PrintState{..},_) -> return (concat (reverse psOutput))- Left err -> error (show err)- titlize = takeWhile (/='.') . upperize . takeFileName- where upperize (x:xs) = toUpper x : xs- upperize xs = xs- examples = map (("docs" </> "snippets") </>)- (map (++".hs")- (words "declarations conditions functions lists data enums patterns ffi dom tail"))--generateJs = do- putStrLn $ "Compiling " ++ inp ++ " to " ++ out ++ " ..."- packageConf <- fmap (lookup "HASKELL_PACKAGE_SANDBOX") getEnvironment- compileFromTo def { configFlattenApps = True- , configTypecheck = False- , configPackageConf = packageConf- } inp (Just out)-- where docs = ("docs" </>)- inp = docs "home.hs"- out = docs "home.js"--page now analytics examples = do- docType- html $ do- head $ thehead- body $ thebody now analytics examples--thehead = do- title $ "The Fay Programming Language — A Haskell subset"- meta ! httpEquiv "Content-Type" ! content "charset=utf-8"- link ! rel "stylesheet" ! type_ "text/css" ! href "home.css"- script ! src "highlight.pack.js" $ return ()- script ! src "jquery.js" $ return ()- script ! src "beautify.js" $ return ()- script ! src "home.js" $ return ()--thebody now analytics examples = do- fork- div !. "wrap" $ do- theheading- theintro- thelinks- thesetup- thejsproblem- thecomparisons- theexamples examples- thereference- thefooter now- preEscapedToMarkup analytics--fork =- a ! href "https://github.com/faylang/fay" $- img ! style "position: absolute; top: 0; right: 0; border: 0;"- ! src "https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"- ! alt "Fork me on GitHub"--theheading = do- div !. "head" $ do- img !. "head-logo" ! src "logo-large.png"- div !. "head-text" $ do- h1 "Fay programming language"- div !. "subheadline" $ "A proper subset of Haskell that compiles to JavaScript"--theexamples examples = do- a ! name "examples" $ return ()- h2 "Examples"- p $ do "The following examples are generated from the "- code "docs/snippets"- " directory in the Fay project distribution. "- "The Fay tab of each example shows the original Fay code, and the "- " JavaScript tab shows the actual generated output of the compiler "- " use to generate this document."- p $ do "Because Fay is lazy, it creates thunks and forces them on a regular basis. "- "Thus, the symbol "; code "$"; " means “thunk”, and the symbol "; code "_"- " means “force”."- forM_ examples $ \(file,fay,javascript) -> do- h3 !. "example-heading" $ toHtml file- div !. "example" $ do- table $ do- tr $ do- td $ do- div !. "panel" $ do- div !. "lang" $ em "Fay"- pre !. "pre" $- code !. "language-haskell" $- toHtml fay- td $ do- div !. "panel" $ do- div !. "lang" $ em "JavaScript"- pre !. "pre" $- code !. "language-javascript" $- toHtml javascript- div !. "example-clear" $ return ()--thefooter now =- div !. "footer" $ do- "© 2012 Chris Done. "- "Document generated on "- toHtml (show now)- " with sexy Haskell. See "- code $ toHtml (takeFileName __FILE__)- " for the source of this document generator."--theintro = do- h2 "Introduction"- p "Fay is a small programming language which has the following properties:"- ul $ do- li $ do "A proper syntactic and semantic subset of "- a ! href "http://haskell.org/" $ "Haskell"- li $ "Statically typed"- li $ "Lazy"- li $ "Pure by default"- li $ "Compiles to JavaScript"- li $ "Has fundamental data types (Double, String, etc.) based upon what JS can support"- li $ "Outputs minifier-aware code for small compressed size"- li $ "Has a trivial foreign function interface to JavaScript"- li $ "Typechecks using GHC"-- p $ a ! href "#examples" $ "Go to examples »"--thejsproblem = do- h2 "The JavaScript Problem"- p "The JavaScript problem is two-fold and can be described thus:"- ul $ do- li $ do strong "JavaScript sucks:"- " The depths to which JavaScript sucks is well-documented and well-understood. Its main faults are: its lack of module system, weak-typing, verbose function syntax, late binding, which has led to the creation of various static analysis tools to alleviate this language flaw, but with limited success (there is even a static type checker), finicky equality/automatic conversion, this behaviour, and lack of static types."- li $ do strong "We need JavaScript:"- " Using it for what it is good for, i.e. providing a platform for browser development, but not using the language per se, is therefore desirable, and many are working to achieve this, in varying forms. There are various ways to do it, but we ought to opt for compiling an existing language, Haskell, to JavaScript, because we do not have time to learn or teach other people a new language, garner a new library set and a new type checker and all that Haskell implementations provide."- p $ a ! href "http://www.haskell.org/haskellwiki/The_JavaScript_Problem" $- "See here for more elaboration »"--thecomparisons = do- h2 "Comparisons to other methods"- coffee- royandelm--coffee = do- h3 "CoffeeScript and LiveScript"- p $ do "CoffeeScript is a syntactic layer above JavaScript that does not change semantics. "- "It adds some additional syntactic constructs, but makes no fundamental changes, "- "you are still essentially working in JavaScript, but with more convenient "- "syntactic features."- p $ do "Fay on the other hand is a different language to JavaScript entirely, with a "- "different semantics. It is lazy, it has partial application and currying, "- "pattern matching for all data types, all expressions are pure and only "- "statements in the Fay monad can be impure."- p $ do "LiveScript is also a similar approach in the wave of compile-to-JS projects "- "that have developed in recent years. LiveScript's translation is also quite "- "readable and predictable, this is also the only thing in common with Fay."--royandelm = do- h3 "Roy and Elm"- p $ do "Roy is an approach to bring functional programming to JavaScript, it has lots of "- "interesting features but it has different syntax and type-system semantics "- "to Haskell."- p $ do "Elm, equally, is an approach to bringing functional programming to the web, "- "and is less generic than Roy, as it specifically focuses on web programming. It, too, "- "borrows from Haskell and looks a bit like it, but is (consciously) different in "- "syntax and semantics."- p $ do "Both of these languages are very interesting and promising approaches. What Fay offers "- "is to keep the existing compiler, GHC, for its battle-tested type checking and "- " code analysis, and to use existing parsers for Haskell to support a subset of its "- "syntax. This way, one does not have to replace the tooling infrastructure and workflow "- "that one is used to. With the exception of actions in the Fay monad, pure functions "- "can be type checked and ran within GHCi."- p $ do "Additionally, because all Fay code "; em "is"; " Haskell code, certain modules "- "can be shared between the ‘native’ Haskell and ‘web’ Haskell, most interestingly "- "the types module of your project. This enables two things:"- ul $ do- li "The enforced (by GHC) coherence of client-side and server-side data types."- li $ do "The transparent serializing and deserializing of data types between these "- "two entities (i.e. over AJAX)."--thesetup = do- h2 "Installation"- p $ do "The Fay compiler is written in Haskell, so you will need "- a ! href "http://hackage.haskell.org/platform/" $ "the Haskell platform"- " installed (or at least Cabal)."- h3 "Cabal install from Hackage"- p "To install, run:"- pre $ code "$ cabal install fay fay-base"- h3 "From Github"- p "If you want to hack on the compiler, you can download the Git repo: "- pre $ code "$ git clone git://github.com/faylang/fay.git"- p "And then install from the directory: "- pre $ code "$ cabal install"- pre $ code "$ cabal install fay-base"- h3 "Running"- p "If developing, you can run the tests (you will need nodejs installed):"- pre $ code "$ cabal install . fay-base/"- pre $ code "$ fay-tests"- p "To compile a Fay program, run:"- pre $ code "$ fay foo.hs"- p $ do "The "; code "--library"; " flag will prevent the "; code "main"; " function from being called."- p "You can also install this via cabal-dev, but be sure to run the commands from the cabal-dev bin dir: "- pre $ code "$ cabal-dev install\n$ cabal-dev install fay-base\n$ cabal-dev/bin/fay --no-ghc foo.hs"- p $ do- "If you only installed with cabal-dev then you will probably get a 'no"- " package fay' error from GHC, so you can tell it where to get the"- " package from with an environment variable:"- pre $ code $- "HASKELL_PACKAGE_SANDBOX=cabal-dev/packages-7.4.1.conf cabal-dev/bin/fay examples/alert.hs"- h3 "Generate this Documentation"- p "This web page is generated by the following call in the project directory:"- pre $ code "$ fay-docs"- p $ do "If you are hacking on the project this can be useful to inspect, and "- "if you add more features, please document them in "; code $ toHtml (takeFileName __FILE__); "."--thereference = do- h2 "Language Reference"- p $ do "To be written. There is a great deal of syntax not yet supported, which I will document. "- "For now it is best to simply try and see if you get an “Unsupported X” compile error or not. "- "It will not accept things that it doesn't support, apart from class and instance declarations, "- "which it ignores entirely. Inspect the compiler source if you are unsure, it is rather simple."--thelinks = do- h2 "Fay in the Wild"- ul $ do- li $ do- "Yesod Blog: "- a ! href- "http://www.yesodweb.com/blog/2012/10/yesod-fay-js" $- "Yesod, AngularJS and Fay"- li $ do- "Happstack Blog: "- a ! href- "http://www.happstack.com/c/view-page-slug/15/happstack-fay-acid-state-shared-datatypes-are-awesome" $- "Happstack, Fay, & Acid-State: Shared Datatypes are Awesome"- li $ do- a ! href- "http://www.skybluetrades.net/blog/posts/2012/11/13/fay-ring-oscillator/index.html" $- "Fun with Fay - A Ring Oscillator"- li $ do- a ! href- "http://cdsmith.wordpress.com/2012/11/18/codeworld-and-the-future/" $- "CodeWorld and the Future"- li $ do- a ! href- "http://ide.fay-lang.org/" $- "A Fay IDE written in Fay"- ": "- a ! href "https://github.com/faylang/fay-server" $ "github"- li $ do- "happstack-fay: "- a ! href "http://hackage.haskell.org/package/happstack-fay" $ "hackage"- li $ do- H.span $ "snaplet-fay: "- a ! href "https://github.com/faylang/snaplet-fay" $ "github"- ", "- a ! href "http://hackage.haskell.org/package/snaplet-fay" $ "hackage"- li $ do- "yesod-fay: "- a ! href "https://github.com/snoyberg/yesod-fay" $ "github"- ", "- a ! href "http://hackage.haskell.org/package/yesod-fay" $ "hackage"- li $ do- "fay-uri: "- a ! href "https://github.com/faylang/fay-uri" $ "github"- " Includes a tutorial to the Fay FFI"- li $ do- "fay-jquery: "- a ! href "https://github.com/faylang/fay-jquery" $ "github"- " With a lot of FFI trickery"
+ src/Fay.hs view
@@ -0,0 +1,187 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE ViewPatterns #-}++-- | Main library entry point.++module Fay+ (module Fay.Types+ ,compileFile+ ,compileFileWithState+ ,compileFromTo+ ,compileFromToAndGenerateHtml+ ,toJsName+ ,showCompileError+ ,getRuntime)+ where++import Fay.Compiler+import Fay.Compiler.Misc (printSrcLoc)+import Fay.Compiler.Packages+import Fay.Compiler.Print+import Fay.Types++import Control.Applicative+import Control.Monad+import Data.List+import qualified Data.Set as S+import Language.Haskell.Exts (prettyPrint)+import Language.Haskell.Exts.Syntax+import Paths_fay+import System.FilePath++-- | Compile the given file and write the output to the given path, or+-- if nothing given, stdout.+compileFromTo :: CompileConfig -> FilePath -> Maybe FilePath -> IO ()+compileFromTo config filein fileout = do+ result <- maybe (compileFile config filein)+ (compileFromToAndGenerateHtml config filein)+ fileout+ case result of+ Right out -> maybe (putStrLn out) (flip writeFile out) fileout+ Left err -> error $ showCompileError $ err++-- | Compile the given file and write to the output, also generate any HTML.+compileFromToAndGenerateHtml :: CompileConfig -> FilePath -> FilePath -> IO (Either CompileError String)+compileFromToAndGenerateHtml config filein fileout = do+ result <- compileFile config { configFilePath = Just filein } filein+ case result of+ Right out -> do+ when (configHtmlWrapper config) $+ writeFile (replaceExtension fileout "html") $ unlines [+ "<!doctype html>"+ , "<html>"+ , " <head>"+ ," <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>"+ , unlines . map (" "++) . map makeScriptTagSrc $ configHtmlJSLibs config+ , " " ++ makeScriptTagSrc relativeJsPath+ , " </script>"+ , " </head>"+ , " <body>"+ , " </body>"+ , "</html>"]+ return (Right out)+ where relativeJsPath = makeRelative (dropFileName fileout) fileout+ makeScriptTagSrc :: FilePath -> String+ makeScriptTagSrc = \s ->+ "<script type=\"text/javascript\" src=\"" ++ s ++ "\"></script>"+ Left err -> return (Left err)++-- | Compile the given file.+compileFile :: CompileConfig -> FilePath -> IO (Either CompileError String)+compileFile config filein = do+ either Left (Right . fst) <$> compileFileWithState config filein++-- | Compile a file returning the state.+compileFileWithState :: CompileConfig -> FilePath -> IO (Either CompileError (String,CompileState))+compileFileWithState config filein = do+ runtime <- getRuntime+ hscode <- readFile filein+ raw <- readFile runtime+ config' <- resolvePackages config+ compileToModule filein config' raw compileToplevelModule hscode++-- | Compile the given module to a runnable module.+compileToModule :: (Show from,Show to,CompilesTo from to)+ => FilePath+ -> CompileConfig -> String -> (from -> Compile to) -> String+ -> IO (Either CompileError (String,CompileState))+compileToModule filepath config raw with hscode = do+ result <- compileViaStr filepath config with hscode+ case result of+ Left err -> return (Left err)+ Right (PrintState{..},state,_) ->+ return $ Right $ (generate (concat (reverse psOutput))+ (S.toList $ getCurrentExports state)+ (stateModuleName state), state)++ where generate | configNaked config = generateNaked+ | otherwise = generateWrapped+ generateNaked jscode _exports _module = unlines $+ [if configExportRuntime config then raw else ""+ ,jscode]+ generateWrapped jscode exports (ModuleName (clean -> modulename)) = unlines $ filter (not . null) $+ ["/** @constructor"+ ,"*/"+ ,"var " ++ modulename ++ " = function(){"+ ,if configExportRuntime config then raw else ""+ ,jscode+ ,"// Exports"+ ,unlines (map printExport exports)+ ,"// Built-ins"+ ,"this._ = Fay$$_;"+ ,if configExportBuiltins config+ then unlines ["this.$ = Fay$$$;"+ ,"this.$fayToJs = Fay$$fayToJs;"+ ,"this.$jsToFay = Fay$$jsToFay;"+ ]+ else ""+ ,"};"+ ,if not (configLibrary config)+ then unlines [";"+ ,"var main = new " ++ modulename ++ "();"+ ,"main._(main." ++ modulename ++ "$main);"+ ]+ else ""+ ]+ clean ('.':cs) = '$' : clean cs+ clean (c:cs) = c : clean cs+ clean [] = []++-- | Print an this.x = x; export out.+printExport :: QName -> String+printExport name =+ printJSString (JsSetProp JsThis+ (JsNameVar name)+ (JsName (JsNameVar name)))++-- | Convert a Haskell filename to a JS filename.+toJsName :: String -> String+toJsName x = case reverse x of+ ('s':'h':'.': (reverse -> file)) -> file ++ ".js"+ _ -> x++-- | Print a compile error for human consumption.+showCompileError :: CompileError -> String+showCompileError e = case e of+ ParseError _ err -> err+ UnsupportedDeclaration d -> "unsupported declaration: " ++ prettyPrint d+ UnsupportedExportSpec es -> "unsupported export specification: " ++ prettyPrint es+ UnsupportedMatchSyntax m -> "unsupported match/binding syntax: " ++ prettyPrint m+ UnsupportedWhereInMatch m -> "unsupported `where' syntax: " ++ prettyPrint m+ UnsupportedWhereInAlt alt -> "`where' not supported here: " ++ prettyPrint alt+ UnsupportedExpression expr -> "unsupported expression syntax: " ++ prettyPrint expr+ UnsupportedQualStmt stmt -> "unsupported list qualifier: " ++ prettyPrint stmt+ UnsupportedLiteral lit -> "unsupported literal syntax: " ++ prettyPrint lit+ UnsupportedLetBinding d -> "unsupported let binding: " ++ prettyPrint d+ UnsupportedOperator qop -> "unsupported operator syntax: " ++ prettyPrint qop+ UnsupportedPattern pat -> "unsupported pattern syntax: " ++ prettyPrint pat+ UnsupportedRhs rhs -> "unsupported right-hand side syntax: " ++ prettyPrint rhs+ UnsupportedGuardedAlts ga -> "unsupported guarded alts: " ++ prettyPrint ga+ EmptyDoBlock -> "empty `do' block"+ UnsupportedModuleSyntax{} -> "unsupported module syntax (may be supported later)"+ LetUnsupported -> "let not supported here"+ InvalidDoBlock -> "invalid `do' block"+ RecursiveDoUnsupported -> "recursive `do' isn't supported"+ FfiNeedsTypeSig d -> "your FFI declaration needs a type signature: " ++ prettyPrint d+ FfiFormatBadChars cs -> "invalid characters for FFI format string: " ++ show cs+ FfiFormatNoSuchArg i -> "no such argument in FFI format string: " ++ show i+ FfiFormatIncompleteArg -> "incomplete `%' syntax in FFI format string"+ FfiFormatInvalidJavaScript srcloc code err ->+ printSrcLoc srcloc ++ ":" +++ "\ninvalid JavaScript code in FFI format string:\n"+ ++ err ++ "\nin " ++ code+ UnsupportedFieldPattern p -> "unsupported field pattern: " ++ prettyPrint p+ UnsupportedImport i -> "unsupported import syntax, we're too lazy: " ++ prettyPrint i+ Couldn'tFindImport i places ->+ "could not find an import in the path: " ++ prettyPrint i ++ ", \n" +++ "searched in these places: " ++ intercalate ", " places+ UnableResolveUnqualified name -> "unable to resolve unqualified name " ++ prettyPrint name+ UnableResolveQualified qname -> "unable to resolve qualified names " ++ prettyPrint qname++-- | Get the JS runtime source.+getRuntime :: IO String+getRuntime = getDataFileName "js/runtime.js"
+ src/Fay/Compiler.hs view
@@ -0,0 +1,224 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE RecordWildCards #-}+{-# OPTIONS -Wall -fno-warn-name-shadowing -fno-warn-orphans #-}++-- | The Haskell→Javascript compiler.++module Fay.Compiler+ (runCompile+ ,compileViaStr+ ,compileForDocs+ ,compileToAst+ ,compileModule+ ,compileExp+ ,compileDecl+ ,compileToplevelModule+ ,parseFay)+ where++import Fay.Compiler.CollectRecords (collectRecords)+import Fay.Compiler.Config+import Fay.Compiler.Defaults+import Fay.Compiler.Exp+import Fay.Compiler.Decl+import Fay.Compiler.FFI+import Fay.Compiler.Misc+import Fay.Compiler.ModuleScope (bindAsLocals, findTopLevelNames, moduleLocals)+import Fay.Compiler.Optimizer+import Fay.Compiler.Typecheck+import Fay.Types++import Control.Applicative+import Control.Monad.Error+import Control.Monad.IO+import Control.Monad.Extra+import Control.Monad.State+import Control.Monad.RWS+import Data.Default (def)+import qualified Data.Set as S+import Data.Maybe+import Language.Haskell.Exts++--------------------------------------------------------------------------------+-- Top level entry points++-- | Compile a Haskell source string to a JavaScript source string.+compileViaStr :: (Show from,Show to,CompilesTo from to)+ => FilePath+ -> CompileConfig+ -> (from -> Compile to)+ -> String+ -> IO (Either CompileError (PrintState,CompileState,CompileWriter))+compileViaStr filepath config with from = do+ cs <- defaultCompileState+ rs <- defaultCompileReader config+ runCompile rs+ (cs { stateFilePath = filepath })+ (parseResult (throwError . uncurry ParseError)+ (fmap (\x -> execState (runPrinter (printJS x)) printConfig) . with)+ (parseFay filepath from))++ where printConfig = def { psPretty = configPrettyPrint config }++-- | Compile a Haskell source string to a JavaScript source string.+compileToAst :: (Show from,Show to,CompilesTo from to)+ => FilePath+ -> CompileReader+ -> CompileState+ -> (from -> Compile to)+ -> String+ -> IO (Either CompileError (to,CompileState,CompileWriter))+compileToAst filepath reader state with from =+ runCompile reader+ state+ (parseResult (throwError . uncurry ParseError)+ with+ (parseFay filepath from))++-- | Compile the given Fay code for the documentation. This is+-- specialised because the documentation isn't really “real”+-- compilation.+compileForDocs :: Module -> Compile [JsStmt]+compileForDocs mod = do+ collectRecords mod+ compileModule False mod++-- | Compile the top-level Fay module.+compileToplevelModule :: Module -> Compile [JsStmt]+compileToplevelModule mod@(Module _ (ModuleName modulename) _ _ _ _ _) = do+ cfg <- config id++ when (configTypecheck cfg) $+ typecheck (configPackageConf cfg) (configWall cfg) $+ fromMaybe modulename $ configFilePath cfg+ collectRecords mod+ cs <- io defaultCompileState+ modify $ \s -> s { stateImported = stateImported cs }+ (stmts,CompileWriter{..}) <- listen $ compileModule True mod+ let fay2js = if null writerFayToJs then [] else [fayToJsDispatcher writerFayToJs]+ js2fay = if null writerJsToFay then [] else [jsToFayDispatcher writerJsToFay]+ maybeOptimize = if configOptimize cfg then runOptimizer optimizeToplevel else id+ if configDispatcherOnly cfg+ then return (maybeOptimize (writerCons ++ fay2js ++ js2fay))+ else return (maybeOptimize (stmts +++ if configDispatchers cfg then writerCons ++ fay2js ++ js2fay else []))++--------------------------------------------------------------------------------+-- Compilers++-- | Compile Haskell module.+compileModule :: Bool -> Module -> Compile [JsStmt]+compileModule toplevel (Module _ modulename _pragmas Nothing exports imports decls) =+ withModuleScope $ do+ modify $ \s -> s { stateModuleName = modulename+ , stateModuleScope = findTopLevelNames modulename decls+ }+ imported <- fmap concat (mapM compileImport imports)+ current <- compileDecls True decls++ case exports of+ Just exps -> mapM_ emitExport exps+ Nothing -> do+ exps <- moduleLocals modulename <$> gets stateModuleScope+ modify $ flip (foldr addCurrentExport) exps++ exportStdlib <- config configExportStdlib+ exportStdlibOnly <- config configExportStdlibOnly+ if exportStdlibOnly+ then if anStdlibModule modulename || toplevel+ then if toplevel+ then return imported+ else return (current ++ imported)+ else return []+ else if not exportStdlib && anStdlibModule modulename+ then return []+ else return (imported ++ current)+compileModule _ mod = throwError (UnsupportedModuleSyntax mod)++instance CompilesTo Module [JsStmt] where compileTo = compileModule False++-- | Is the module a standard module, i.e., one that we'd rather not+-- output code for if we're compiling separate files.+anStdlibModule :: ModuleName -> Bool+anStdlibModule (ModuleName name) = elem name ["Prelude","FFI","Language.Fay.FFI","Data.Data"]++-- | Compile the given import.+compileImport :: ImportDecl -> Compile [JsStmt]+compileImport (ImportDecl _ _ _ _ Just{} _ _) = do+-- warn $ "import with package syntax ignored: " ++ prettyPrint i+ return []+compileImport (ImportDecl _ name False _ Nothing Nothing Nothing) =+ compileImportWithFilter name (const $ return True)+compileImport (ImportDecl _ name False _ Nothing Nothing (Just (True, specs))) =+ compileImportWithFilter name (fmap not . imported specs)+compileImport (ImportDecl _ name False _ Nothing Nothing (Just (False, specs))) =+ compileImportWithFilter name (imported specs)+compileImport i =+ throwError $ UnsupportedImport i++imported :: [ImportSpec] -> QName -> Compile Bool+imported is qn = anyM (matching qn) is+ where+ matching :: QName -> ImportSpec -> Compile Bool+ matching (Qual _ _) (IAbs _) = return True -- Types are always OK+ matching (Qual _ name) (IVar var) = return $ name == var+ matching (Qual _ name) (IThingAll typ) = do+ recs <- typeToRecs $ UnQual typ+ if UnQual name `elem` recs+ then return True+ else do+ fields <- typeToFields $ UnQual typ+ return $ UnQual name `elem` fields+ matching (Qual _ name) (IThingWith typ cns) =+ flip anyM cns $ \cn -> case cn of+ ConName _ -> do+ recs <- typeToRecs $ UnQual typ+ return $ UnQual name `elem` recs+ VarName _ -> do+ fields <- typeToFields $ UnQual typ+ return $ UnQual name `elem` fields+ matching q is = error $ "compileImport: Unsupported QName ImportSpec combination " ++ show (q, is) ++ ", this is a bug!"+++compileImportWithFilter :: ModuleName -> (QName -> Compile Bool) -> Compile [JsStmt]+compileImportWithFilter name importFilter =+ unlessImported name importFilter $ \filepath contents -> do+ state <- get+ reader <- ask+ result <- liftIO $ compileToAst filepath reader state (compileModule False) contents+ case result of+ Right (stmts,state,writer) -> do+ imports <- filterM importFilter $ S.toList $ getCurrentExports state+ tell writer+ modify $ \s -> s { stateImported = stateImported state+ , stateLocalScope = S.empty+ , stateModuleScope = bindAsLocals imports (stateModuleScope s)+ , _stateExports = _stateExports state+ }+ return stmts+ Left err -> throwError err++unlessImported :: ModuleName+ -> (QName -> Compile Bool)+ -> (FilePath -> String -> Compile [JsStmt])+ -> Compile [JsStmt]+unlessImported "Fay.Types" _ _ = return []+unlessImported name importFilter importIt = do+ imported <- gets stateImported+ case lookup name imported of+ Just _ -> do+ exports <- gets $ getExportsFor name+ imports <- filterM importFilter $ S.toList exports+ modify $ \s -> s { stateModuleScope = bindAsLocals imports (stateModuleScope s) }+ return []+ Nothing -> do+ dirs <- configDirectoryIncludePaths <$> config id+ (filepath,contents) <- findImport dirs name+ res <- importIt filepath contents+ -- TODO stateImported is already added in initialPass so it is not needed here+ -- but one Api test fails if it's removed.+ modify $ \s -> s { stateImported = (name,filepath) : imported+ }+ return res
+ src/Fay/Compiler/CollectRecords.hs view
@@ -0,0 +1,118 @@+{-# LANGUAGE OverloadedStrings #-}++-- | Initial pass-through collecting record definitions++module Fay.Compiler.CollectRecords where++import Fay.Compiler.Misc+import Fay.Types+import Fay.Compiler.Config++import Control.Applicative+import Control.Monad.Error+import Control.Monad.RWS+import Language.Haskell.Exts.Syntax+import Language.Haskell.Exts.Parser++-- | Collect all the records and their fields before compiling.+collectRecords :: Module -> Compile ()+collectRecords (Module _ _ _ Nothing _ imports decls) = do+ mapM_ passImport imports+ mapM_ scanDecl decls+collectRecords m = throwError (UnsupportedModuleSyntax m)++-- | Handle an import.+passImport :: ImportDecl -> Compile ()+passImport (ImportDecl _ _ _ _ Just{} _ _) = do+ return ()+-- warn $ "import with package syntax ignored: " ++ prettyPrint i+passImport (ImportDecl _ name False _ Nothing Nothing _) = do+ void $ unlessImported name $ \filepath contents -> do+ state' <- get+ reader' <- ask+ result <- liftIO $ records filepath reader' state' collectRecords contents+ case result of+ Right ((),st,_) -> do+ -- Merges the state gotten from passing through an imported+ -- module with the current state. We can assume no duplicate+ -- records exist since GHC would pick that up.+ modify $ \s -> s { stateRecords = stateRecords st+ , stateRecordTypes = stateRecordTypes st+ , stateImported = stateImported st+ }+ Left err -> throwError err+ return ()+passImport i = throwError $ UnsupportedImport i++-- | Don't re-import the same modules.+unlessImported :: ModuleName+ -> (FilePath -> String -> Compile ())+ -> Compile ()+unlessImported name importIt = do+ imported <- gets stateImported+ case lookup name imported of+ Just _ -> return ()+ Nothing -> do+ dirs <- configDirectoryIncludePaths <$> config id+ (filepath,contents) <- findImport dirs name+ modify $ \s -> s { stateImported = (name,filepath) : imported }+ importIt filepath contents++-- | Compile only for record generation.+records :: (Show from,Parseable from)+ => FilePath+ -> CompileReader+ -> CompileState+ -> (from -> Compile ())+ -> String+ -> IO (Either CompileError ((),CompileState,CompileWriter))+records filepath compileReader compileState with from =+ runCompile compileReader+ compileState+ (parseResult (throwError . uncurry ParseError)+ with+ (parseFay filepath from))++-- | Handle a declaration.+scanDecl :: Decl -> Compile ()+scanDecl decl = do+ case decl of+ DataDecl _loc DataType _ctx name _tyvarb qualcondecls _deriv -> do+ let ns = flip map qualcondecls (\(QualConDecl _loc' _tyvarbinds _ctx' condecl) -> conDeclName condecl)+ addRecordTypeState name ns+ _ -> return ()+++ case decl of+ DataDecl _ DataType _ _ _ constructors _ -> dataDecl constructors+ GDataDecl _ DataType _l _i _v _n decls _ -> dataDecl (map convertGADT decls)+ _ -> return ()++ where+ addRecordTypeState name cons = modify $ \s -> s+ { stateRecordTypes = (UnQual name, map UnQual cons) : stateRecordTypes s }++ conDeclName (ConDecl n _) = n+ conDeclName (InfixConDecl _ n _) = n+ conDeclName (RecDecl n _) = n+++-- | Collect record definitions and store record name and field names.+-- A ConDecl will have fields named slot1..slotN+dataDecl :: [QualConDecl] -> Compile ()+dataDecl constructors = do+ forM_ constructors $ \(QualConDecl _ _ _ condecl) ->+ case condecl of+ ConDecl name types -> do+ let fields = map (Ident . ("slot"++) . show . fst) . zip [1 :: Integer ..] $ types+ addRecordState name fields+ InfixConDecl _t1 name _t2 ->+ addRecordState name ["slot1", "slot2"]+ RecDecl name fields' -> do+ let fields = concatMap fst fields'+ addRecordState name fields++ where+ addRecordState :: Name -> [Name] -> Compile ()+ addRecordState name fields = modify $ \s -> s+ { stateRecords = (UnQual name,map UnQual fields) : stateRecords s }
+ src/Fay/Compiler/Config.hs view
@@ -0,0 +1,65 @@+{-# OPTIONS -fno-warn-orphans #-}++-- | Configuration functions.++module Fay.Compiler.Config where++import Data.Default+import Data.Maybe+import Fay.Types++-- | Get all include directories without the package mapping.+configDirectoryIncludePaths :: CompileConfig -> [FilePath]+configDirectoryIncludePaths = map snd . configDirectoryIncludes++-- | Get all include directories not included through packages.+nonPackageConfigDirectoryIncludePaths :: CompileConfig -> [FilePath]+nonPackageConfigDirectoryIncludePaths = map snd . filter (isJust . fst) . configDirectoryIncludes++-- | Add a mapping from (maybe) a package to a source directory+addConfigDirectoryInclude :: Maybe String -> FilePath -> CompileConfig -> CompileConfig+addConfigDirectoryInclude pkg fp cfg = cfg { configDirectoryIncludes = (pkg, fp) : configDirectoryIncludes cfg }++-- | Add several include directories.+addConfigDirectoryIncludes :: [(Maybe String,FilePath)] -> CompileConfig -> CompileConfig+addConfigDirectoryIncludes pkgFps cfg = foldl (\c (pkg,fp) -> addConfigDirectoryInclude pkg fp c) cfg pkgFps++-- | Add several include directories without package references.+addConfigDirectoryIncludePaths :: [FilePath] -> CompileConfig -> CompileConfig+addConfigDirectoryIncludePaths fps cfg = foldl (flip (addConfigDirectoryInclude Nothing)) cfg fps++-- | Add a package to compilation+addConfigPackage :: String -> CompileConfig -> CompileConfig+addConfigPackage pkg cfg = cfg { configPackages = pkg : configPackages cfg }++-- | Add several packages to compilation+addConfigPackages :: [String] -> CompileConfig -> CompileConfig+addConfigPackages fps cfg = foldl (flip addConfigPackage) cfg fps++-- | Default configuration.+instance Default CompileConfig where+ def =+ addConfigPackage "fay-base" $+ CompileConfig+ { configOptimize = False+ , configFlattenApps = False+ , configExportBuiltins = True+ , configExportRuntime = True+ , configExportStdlib = True+ , configExportStdlibOnly = False+ , configDispatchers = True+ , configDispatcherOnly = False+ , configNaked = False+ , configDirectoryIncludes = []+ , configPrettyPrint = False+ , configHtmlWrapper = False+ , configHtmlJSLibs = []+ , configLibrary = False+ , configWarn = True+ , configFilePath = Nothing+ , configTypecheck = True+ , configWall = False+ , configGClosure = False+ , configPackageConf = Nothing+ , configPackages = []+ }
+ src/Fay/Compiler/Debug.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE RecordWildCards #-}++-- | Some useful debug functions.++module Fay.Compiler.Debug where++import Fay.Compiler.Defaults+import Fay.Compiler+import Fay.Compiler.Misc (parseResult)+import Fay.Types++import Control.Monad.Error+import Data.Default++-- | Compile a String of Fay and print it as beautified JavaScript.+printTestCompile :: String -> IO ()+printTestCompile = printCompile def { configWarn = False } (compileModule False)++-- | Compile a Haskell source string to a JavaScript source string.+compileTestAst :: (Show from,Show to,CompilesTo from to)+ => CompileConfig+ -> (from -> Compile to)+ -> String+ -> IO ()+compileTestAst cfg with from = do+ state <- defaultCompileState+ reader <- defaultCompileReader cfg+ out <- runCompile reader+ state+ (parseResult (throwError . uncurry ParseError)+ with+ (parseFay "<interactive>" from))+ case out of+ Left err -> error $ show err+ Right (ok,_,_) -> print ok++-- | Print a useful debug output of a compilation.+debug :: (Show from,Show to,CompilesTo from to) => (from -> Compile to) -> String -> IO ()+debug compile string = do+ putStrLn "AST:\n"+ compileTestAst c compile string+ putStrLn ""+ putStrLn "JS (unoptimized):\n"+ printCompile def { configTypecheck = False } compile string+ putStrLn "JS (optimized):\n"+ printCompile c compile string++ where c = def { configOptimize = True, configTypecheck = False }++-- | Compile the given input and print the output out prettily.+printCompile :: (Show from,Show to,CompilesTo from to)+ => CompileConfig+ -> (from -> Compile to)+ -> String+ -> IO ()+printCompile config with from = do+ result <- compileViaStr "<interactive>" config { configPrettyPrint = True } with from+ case result of+ Left err -> print err+ Right (PrintState{..},_,_) -> do+ putStrLn (concat (reverse (psOutput)))
+ src/Fay/Compiler/Decl.hs view
@@ -0,0 +1,204 @@+{-# OPTIONS -fno-warn-orphans -fno-warn-name-shadowing #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ViewPatterns #-}++-- | Compile declarations.++module Fay.Compiler.Decl where++import Fay.Compiler.Exp+import Fay.Compiler.FFI+import Fay.Compiler.Misc+import Fay.Compiler.Pattern+import Fay.Types++import Control.Applicative+import Control.Monad.Error+import Data.List.Extra+import Control.Monad.RWS+import Language.Haskell.Exts++-- | Compile Haskell declaration.+compileDecls :: Bool -> [Decl] -> Compile [JsStmt]+compileDecls toplevel decls =+ case decls of+ [] -> return []+ (TypeSig _ _ sig:bind@PatBind{}:decls) -> appendM (scoped (compilePatBind toplevel (Just sig) bind))+ (compileDecls toplevel decls)+ (decl:decls) -> appendM (scoped (compileDecl toplevel decl))+ (compileDecls toplevel decls)++ where appendM m n = do x <- m+ xs <- n+ return (x ++ xs)+ scoped = if toplevel then withScope else id++-- | Compile a declaration.+compileDecl :: Bool -> Decl -> Compile [JsStmt]+compileDecl toplevel decl =+ case decl of+ pat@PatBind{} -> compilePatBind toplevel Nothing pat+ FunBind matches -> compileFunCase toplevel matches+ DataDecl _ DataType _ _ _ constructors _ -> compileDataDecl toplevel decl constructors+ GDataDecl _ DataType _l _i _v _n decls _ -> compileDataDecl toplevel decl (map convertGADT decls)+ -- Just ignore type aliases and signatures.+ TypeDecl{} -> return []+ TypeSig{} -> return []+ InfixDecl{} -> return []+ ClassDecl{} -> return []+ InstDecl{} -> return [] -- FIXME: Ignore.+ DerivDecl{} -> return []+ _ -> throwError (UnsupportedDeclaration decl)++-- | Convenient instance.+instance CompilesTo Decl [JsStmt] where compileTo = compileDecl True++-- | Compile a top-level pattern bind.+compilePatBind :: Bool -> Maybe Type -> Decl -> Compile [JsStmt]+compilePatBind toplevel sig pat =+ case pat of+ PatBind srcloc (PVar ident) Nothing (UnGuardedRhs rhs) (BDecls []) ->+ case ffiExp rhs of+ Just formatstr -> case sig of+ Just sig -> compileFFI srcloc ident formatstr sig+ Nothing -> throwError (FfiNeedsTypeSig pat)+ _ -> compileUnguardedRhs srcloc toplevel ident rhs+ PatBind srcloc (PVar ident) Nothing (UnGuardedRhs rhs) bdecls -> do+ compileUnguardedRhs srcloc toplevel ident (Let bdecls rhs)+ _ -> throwError (UnsupportedDeclaration pat)++ where ffiExp (App (Var (UnQual (Ident "ffi"))) (Lit (String formatstr))) = Just formatstr+ ffiExp _ = Nothing++-- | Compile a normal simple pattern binding.+compileUnguardedRhs :: SrcLoc -> Bool -> Name -> Exp -> Compile [JsStmt]+compileUnguardedRhs srcloc toplevel ident rhs = do+ unless toplevel $ bindVar ident+ withScope $ do+ body <- compileExp rhs+ bind <- bindToplevel srcloc toplevel ident (thunk body)+ return [bind]++-- | Compile a data declaration.+compileDataDecl :: Bool -> Decl -> [QualConDecl] -> Compile [JsStmt]+compileDataDecl toplevel _decl constructors =+ fmap concat $+ forM constructors $ \(QualConDecl srcloc _ _ condecl) ->+ case condecl of+ ConDecl name types -> do+ let fields = map (Ident . ("slot"++) . show . fst) . zip [1 :: Integer ..] $ types+ fields' = (zip (map return fields) types)+ cons <- makeConstructor name fields+ func <- makeFunc name fields+ emitFayToJs name fields'+ emitJsToFay name fields'+ emitCons cons+ return [func]+ InfixConDecl t1 name t2 -> do+ let slots = ["slot1","slot2"]+ fields = zip (map return slots) [t1, t2]+ cons <- makeConstructor name slots+ func <- makeFunc name slots+ emitFayToJs name fields+ emitJsToFay name fields+ emitCons cons+ return [func]+ RecDecl name fields' -> do+ let fields = concatMap fst fields'+ cons <- makeConstructor name fields+ func <- makeFunc name fields+ funs <- makeAccessors srcloc fields+ emitFayToJs name fields'+ emitJsToFay name fields'+ emitCons cons+ return (func : funs)++ where+ emitCons cons = tell (mempty { writerCons = [cons] })++ -- Creates a constructor R_RecConstr for a Record+ makeConstructor :: Name -> [Name] -> Compile JsStmt+ makeConstructor name (map (JsNameVar . UnQual) -> fields) = do+ qname <- qualify name+ emitExport (EVar qname)+ return $+ JsVar (JsConstructor qname) $+ JsFun fields (for fields $ \field -> JsSetProp JsThis field (JsName field))+ Nothing++ -- Creates a function to initialize the record by regular application+ makeFunc :: Name -> [Name] -> Compile JsStmt+ makeFunc name (map (JsNameVar . UnQual) -> fields) = do+ let fieldExps = map JsName fields+ qname <- qualify name+ return $ JsVar (JsNameVar qname) $+ foldr (\slot inner -> JsFun [slot] [] (Just inner))+ (thunk $ JsNew (JsConstructor qname) fieldExps)+ fields++ -- Creates getters for a RecDecl's values+ makeAccessors :: SrcLoc -> [Name] -> Compile [JsStmt]+ makeAccessors srcloc fields =+ forM fields $ \name ->+ bindToplevel srcloc+ toplevel+ name+ (JsFun [JsNameVar "x"]+ []+ (Just (thunk (JsGetProp (force (JsName (JsNameVar "x")))+ (JsNameVar (UnQual name))))))++-- | Compile a function which pattern matches (causing a case analysis).+compileFunCase :: Bool -> [Match] -> Compile [JsStmt]+compileFunCase _toplevel [] = return []+compileFunCase toplevel matches@(Match srcloc name argslen _ _ _:_) = do+ pats <- fmap optimizePatConditions (mapM compileCase matches)+ bindVar name+ bind <- bindToplevel srcloc+ toplevel+ name+ (foldr (\arg inner -> JsFun [arg] [] (Just inner))+ (stmtsThunk (concat pats ++ basecase))+ args)+ return [bind]+ where args = zipWith const uniqueNames argslen++ isWildCardMatch (Match _ _ pats _ _ _) = all isWildCardPat pats++ compileCase :: Match -> Compile [JsStmt]+ compileCase match@(Match _ _ pats _ rhs _) = do+ withScope $ do+ whereDecls' <- whereDecls match+ generateScope $ zipWithM (\arg pat -> compilePat (JsName arg) pat []) args pats+ generateScope $ mapM compileLetDecl whereDecls'+ rhsform <- compileRhs rhs+ body <- if null whereDecls'+ then return $ either id JsEarlyReturn rhsform+ else do+ binds <- mapM compileLetDecl whereDecls'+ return $ case rhsform of+ Right exp ->+ (JsEarlyReturn (JsApp (JsFun [] (concat binds) (Just exp)) []))+ Left stmt ->+ (JsEarlyReturn (JsApp (JsFun [] (concat binds ++ [stmt]) Nothing) []))+ foldM (\inner (arg,pat) ->+ compilePat (JsName arg) pat inner)+ [body]+ (zip args pats)++ whereDecls :: Match -> Compile [Decl]+ whereDecls (Match _ _ _ _ _ (BDecls decls)) = return decls+ whereDecls match = throwError (UnsupportedWhereInMatch match)++ basecase :: [JsStmt]+ basecase = if any isWildCardMatch matches+ then []+ else [throw ("unhandled case in " ++ prettyPrint name)+ (JsList (map JsName args))]++-- | Compile a right-hand-side expression.+compileRhs :: Rhs -> Compile (Either JsStmt JsExp)+compileRhs (UnGuardedRhs exp) = Right <$> compileExp exp+compileRhs (GuardedRhss rhss) = Left <$> compileGuards rhss
+ src/Fay/Compiler/Defaults.hs view
@@ -0,0 +1,42 @@+{-# LANGUAGE OverloadedStrings #-}++-- | Default values.++module Fay.Compiler.Defaults where++import Fay.Compiler.Config+import Fay.Compiler.Decl (compileDecls)+import Fay.Compiler.Exp (compileLit)+import Fay.Types++import Data.Default+import Data.Map as M+import Data.Set as S+import Language.Haskell.Exts.Syntax+import Paths_fay++-- | The default compiler reader value.+defaultCompileReader :: CompileConfig -> IO CompileReader+defaultCompileReader config = do+ srcdir <- faySourceDir+ return CompileReader+ { readerConfig = addConfigDirectoryInclude Nothing srcdir config+ , readerCompileLit = compileLit+ , readerCompileDecls = compileDecls+ }++-- | The default compiler state.+defaultCompileState :: IO CompileState+defaultCompileState = do+ types <- getDataFileName "src/Language/Fay/Types.hs"+ return $ CompileState {+ _stateExports = M.empty+ , stateModuleName = ModuleName "Main"+ , stateRecordTypes = []+ , stateRecords = []+ , stateImported = [("Fay.Types",types)]+ , stateNameDepth = 1+ , stateFilePath = "<unknown>"+ , stateLocalScope = S.empty+ , stateModuleScope = def+ }
+ src/Fay/Compiler/Exp.hs view
@@ -0,0 +1,404 @@+{-# OPTIONS -fno-warn-name-shadowing -fno-warn-orphans #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE MultiParamTypeClasses #-}++-- | Compile expressions++module Fay.Compiler.Exp where++import Fay.Compiler.Misc+import Fay.Compiler.Pattern+import Fay.Compiler.Print+import Fay.Types++import Control.Applicative+import Control.Monad.Error+import Control.Monad.RWS+import Data.Maybe+import Language.Haskell.Exts++-- | Compile Haskell expression.+compileExp :: Exp -> Compile JsExp+compileExp exp =+ case exp of+ Paren exp -> compileExp exp+ Var qname -> compileVar qname+ Lit lit -> compileLit lit+ App exp1 exp2 -> compileApp exp1 exp2+ NegApp exp -> compileNegApp exp+ InfixApp exp1 op exp2 -> compileInfixApp exp1 op exp2+ Let (BDecls decls) exp -> compileLet decls exp+ List [] -> return JsNull+ List xs -> compileList xs+ Tuple xs -> compileList xs+ If cond conseq alt -> compileIf cond conseq alt+ Case exp alts -> compileCase exp alts+ Con (UnQual (Ident "True")) -> return (JsLit (JsBool True))+ Con (UnQual (Ident "False")) -> return (JsLit (JsBool False))+ Con qname -> compileVar qname+ Do stmts -> compileDoBlock stmts+ Lambda _ pats exp -> compileLambda pats exp+ LeftSection e o -> compileExp =<< desugarLeftSection e o+ RightSection o e -> compileExp =<< desugarRightSection o e+ EnumFrom i -> compileEnumFrom i+ EnumFromTo i i' -> compileEnumFromTo i i'+ EnumFromThen a b -> compileEnumFromThen a b+ EnumFromThenTo a b z -> compileEnumFromThenTo a b z+ RecConstr name fieldUpdates -> compileRecConstr name fieldUpdates+ RecUpdate rec fieldUpdates -> updateRec rec fieldUpdates+ ListComp exp stmts -> compileExp =<< desugarListComp exp stmts+ ExpTypeSig _ e _ -> compileExp e++ exp -> throwError (UnsupportedExpression exp)++-- | Compiling instance.+instance CompilesTo Exp JsExp where compileTo = compileExp++-- | Compile variable.+compileVar :: QName -> Compile JsExp+compileVar qname = do+ qname <- resolveName qname+ return (JsName (JsNameVar qname))++-- | Compile Haskell literal.+compileLit :: Literal -> Compile JsExp+compileLit lit =+ case lit of+ Char ch -> return (JsLit (JsChar ch))+ Int integer -> return (JsLit (JsInt (fromIntegral integer))) -- FIXME:+ Frac rational -> return (JsLit (JsFloating (fromRational rational)))+ -- TODO: Use real JS strings instead of array, probably it will+ -- lead to the same result.+ String string -> return (JsApp (JsName (JsBuiltIn "list"))+ [JsLit (JsStr string)])+ lit -> throwError (UnsupportedLiteral lit)++-- | Compile simple application.+compileApp :: Exp -> Exp -> Compile JsExp+compileApp exp1 exp2 = do+ flattenApps <- config configFlattenApps+ if flattenApps then method2 else method1+ where+ -- Method 1:+ -- In this approach code ends up looking like this:+ -- a(a(a(a(a(a(a(a(a(a(L)(c))(b))(0))(0))(y))(t))(a(a(F)(3*a(a(d)+a(a(f)/20))))*a(a(f)/2)))(140+a(f)))(y))(t)})+ -- Which might be OK for speed, but increases the JS stack a fair bit.+ method1 =+ JsApp <$> (forceFlatName <$> compileExp exp1)+ <*> fmap return (compileExp exp2)+ forceFlatName name = JsApp (JsName JsForce) [name]++ -- Method 2:+ -- In this approach code ends up looking like this:+ -- d(O,a,b,0,0,B,w,e(d(I,3*e(e(c)+e(e(g)/20))))*e(e(g)/2),140+e(g),B,w)}),d(K,g,e(c)+0.05))+ -- Which should be much better for the stack and readability, but probably not great for speed.+ method2 = fmap flatten $+ JsApp <$> compileExp exp1+ <*> fmap return (compileExp exp2)+ flatten (JsApp op args) =+ case op of+ JsApp l r -> JsApp l (r ++ args)+ _ -> JsApp (JsName JsApply) (op : args)+ flatten x = x++-- | Compile a negate application+compileNegApp :: Exp -> Compile JsExp+compileNegApp e = JsNegApp . force <$> compileExp e++-- | Compile an infix application, optimizing the JS cases.+compileInfixApp :: Exp -> QOp -> Exp -> Compile JsExp+compileInfixApp exp1 ap exp2 = compileExp (App (App (Var op) exp1) exp2)++ where op = getOp ap+ getOp (QVarOp op) = op+ getOp (QConOp op) = op++-- | Compile a let expression.+compileLet :: [Decl] -> Exp -> Compile JsExp+compileLet decls exp = do+ withScope $ do+ generateScope $ mapM compileLetDecl decls+ binds <- mapM compileLetDecl decls+ body <- compileExp exp+ return (JsApp (JsFun [] (concat binds) (Just body)) [])++-- | Compile let declaration.+compileLetDecl :: Decl -> Compile [JsStmt]+compileLetDecl decl = do+ compileDecls <- asks readerCompileDecls+ v <- case decl of+ decl@PatBind{} -> compileDecls False [decl]+ decl@FunBind{} -> compileDecls False [decl]+ TypeSig{} -> return []+ _ -> throwError (UnsupportedLetBinding decl)+ return v++-- | Compile a list expression.+compileList :: [Exp] -> Compile JsExp+compileList xs = do+ exps <- mapM compileExp xs+ return (makeList exps)++-- | Compile an if.+compileIf :: Exp -> Exp -> Exp -> Compile JsExp+compileIf cond conseq alt =+ JsTernaryIf <$> fmap force (compileExp cond)+ <*> compileExp conseq+ <*> compileExp alt++-- | Compile case expressions.+compileCase :: Exp -> [Alt] -> Compile JsExp+compileCase exp alts = do+ exp <- compileExp exp+ withScopedTmpJsName $ \tmpName -> do+ pats <- fmap optimizePatConditions $ mapM (compilePatAlt (JsName tmpName)) alts+ return $+ JsApp (JsFun [tmpName]+ (concat pats)+ (if any isWildCardAlt alts+ then Nothing+ else Just (throwExp "unhandled case" (JsName tmpName))))+ [exp]++-- | Compile the given pattern against the given expression.+compilePatAlt :: JsExp -> Alt -> Compile [JsStmt]+compilePatAlt exp alt@(Alt _ pat rhs wheres) = case wheres of+ BDecls (_ : _) -> throwError (UnsupportedWhereInAlt alt)+ IPBinds (_ : _) -> throwError (UnsupportedWhereInAlt alt)+ _ -> withScope $ do+ generateScope $ compilePat exp pat []+ alt <- compileGuardedAlt rhs+ compilePat exp pat [alt]++-- | Compile a guarded alt.+compileGuardedAlt :: GuardedAlts -> Compile JsStmt+compileGuardedAlt alt =+ case alt of+ UnGuardedAlt exp -> JsEarlyReturn <$> compileExp exp+ GuardedAlts alts -> compileGuards (map altToRhs alts)+ where+ altToRhs (GuardedAlt l s e) = GuardedRhs l s e++-- | Compile guards+compileGuards :: [GuardedRhs] -> Compile JsStmt+compileGuards ((GuardedRhs _ (Qualifier (Var (UnQual (Ident "otherwise"))):_) exp):_) =+ (\e -> JsIf (JsLit (JsBool True)) [JsEarlyReturn e] []) <$> compileExp exp+compileGuards (GuardedRhs _ (Qualifier guard:_) exp : rest) =+ makeIf <$> fmap force (compileExp guard)+ <*> compileExp exp+ <*> if null rest then (return []) else do+ gs' <- compileGuards rest+ return [gs']+ where makeIf gs e gss = JsIf gs [JsEarlyReturn e] gss++compileGuards rhss = throwError . UnsupportedRhs . GuardedRhss $ rhss++-- | Compile a do block.+compileDoBlock :: [Stmt] -> Compile JsExp+compileDoBlock stmts = do+ doblock <- foldM compileStmt Nothing (reverse stmts)+ maybe (throwError EmptyDoBlock) compileExp doblock++-- | Compile a lambda.+compileLambda :: [Pat] -> Exp -> Compile JsExp+compileLambda pats exp = do+ withScope $ do+ generateScope $ generateStatements JsNull+ exp <- compileExp exp+ stmts <- generateStatements exp+ case stmts of+ [JsEarlyReturn fun@JsFun{}] -> return fun+ _ -> error "Unexpected statements in compileLambda"++ where unhandledcase = throw "unhandled case" . JsName+ allfree = all isWildCardPat pats+ generateStatements exp =+ foldM (\inner (param,pat) -> do+ stmts <- compilePat (JsName param) pat inner+ return [JsEarlyReturn (JsFun [param] (stmts ++ [unhandledcase param | not allfree]) Nothing)])+ [JsEarlyReturn exp]+ (reverse (zip uniqueNames pats))++-- | Desugar left sections to lambdas.+desugarLeftSection :: Exp -> QOp -> Compile Exp+desugarLeftSection e o = withScopedTmpName $ \tmp ->+ return (Lambda undefined [PVar tmp] (InfixApp e o (Var (UnQual tmp))))++-- | Desugar left sections to lambdas.+desugarRightSection :: QOp -> Exp -> Compile Exp+desugarRightSection o e = withScopedTmpName $ \tmp ->+ return (Lambda undefined [PVar tmp] (InfixApp (Var (UnQual tmp)) o e))++-- | Compile [e1..] arithmetic sequences.+compileEnumFrom :: Exp -> Compile JsExp+compileEnumFrom i = do+ e <- compileExp i+ name <- resolveName "enumFrom"+ return (JsApp (JsName (JsNameVar name)) [e])++-- | Compile [e1..e3] arithmetic sequences.+compileEnumFromTo :: Exp -> Exp -> Compile JsExp+compileEnumFromTo i i' = do+ f <- compileExp i+ t <- compileExp i'+ name <- resolveName "enumFromTo"+ cfg <- config id+ return $ case optEnumFromTo cfg f t of+ Just s -> s+ _ -> JsApp (JsApp (JsName (JsNameVar name)) [f]) [t]++-- | Compile [e1,e2..] arithmetic sequences.+compileEnumFromThen :: Exp -> Exp -> Compile JsExp+compileEnumFromThen a b = do+ fr <- compileExp a+ th <- compileExp b+ name <- resolveName "enumFromThen"+ return (JsApp (JsApp (JsName (JsNameVar name)) [fr]) [th])++-- | Compile [e1,e2..e3] arithmetic sequences.+compileEnumFromThenTo :: Exp -> Exp -> Exp -> Compile JsExp+compileEnumFromThenTo a b z = do+ fr <- compileExp a+ th <- compileExp b+ to <- compileExp z+ name <- resolveName "enumFromThenTo"+ cfg <- config id+ return $ case optEnumFromThenTo cfg fr th to of+ Just s -> s+ _ -> JsApp (JsApp (JsApp (JsName (JsNameVar name)) [fr]) [th]) [to]++-- | Compile a record construction with named fields+-- | GHC will warn on uninitialized fields, they will be undefined in JS.+compileRecConstr :: QName -> [FieldUpdate] -> Compile JsExp+compileRecConstr name fieldUpdates = do+ -- var obj = new $_Type()+ qname <- resolveName name+ let record = JsVar (JsNameVar name) (JsNew (JsConstructor qname) [])+ setFields <- liftM concat (forM fieldUpdates (updateStmt name))+ return $ JsApp (JsFun [] (record:setFields) (Just (JsName (JsNameVar name)))) []+ where updateStmt :: QName -> FieldUpdate -> Compile [JsStmt]+ updateStmt o (FieldUpdate field value) = do+ exp <- compileExp value+ return [JsSetProp (JsNameVar o) (JsNameVar field) exp]+ updateStmt name FieldWildcard = do+ records <- liftM stateRecords get+ let fields = fromJust (lookup name records)+ return (map (\fieldName -> JsSetProp (JsNameVar name)+ (JsNameVar fieldName)+ (JsName (JsNameVar fieldName)))+ fields)+ -- TODO: FieldPun+ -- I couldn't find a code that generates (FieldUpdate (FieldPun ..))+ updateStmt _ u = error ("updateStmt: " ++ show u)++-- | Update a record (using clever Object.create(), dunno if this is cross-browser).+updateRec :: Exp -> [FieldUpdate] -> Compile JsExp+updateRec rec fieldUpdates = do+ record <- force <$> compileExp rec+ let copyName = UnQual (Ident "$_record_to_update")+ copy = JsVar (JsNameVar copyName)+ (JsRawExp ("Object.create(" ++ printJSString record ++ ")"))+ setFields <- forM fieldUpdates (updateExp copyName)+ return $ JsApp (JsFun [] (copy:setFields) (Just (JsName (JsNameVar copyName)))) []+ where updateExp :: QName -> FieldUpdate -> Compile JsStmt+ updateExp copyName (FieldUpdate field value) =+ JsSetProp (JsNameVar copyName) (JsNameVar field) <$> compileExp value+ updateExp copyName (FieldPun name) =+ -- let a = 1 in C {a}+ return $ JsSetProp (JsNameVar copyName)+ (JsNameVar (UnQual name))+ (JsName (JsNameVar (UnQual name)))+ -- TODO: FieldWildcard+ -- I also couldn't find a code that generates (FieldUpdate FieldWildCard)+ updateExp _ FieldWildcard = error "unsupported update: FieldWildcard"++-- | Desugar list comprehensions.+desugarListComp :: Exp -> [QualStmt] -> Compile Exp+desugarListComp e [] =+ return (List [ e ])+desugarListComp e (QualStmt (Generator loc p e2) : stmts) = do+ nested <- desugarListComp e stmts+ withScopedTmpName $ \f ->+ return (Let (BDecls [ FunBind [+ Match loc f [ p ] Nothing (UnGuardedRhs nested) (BDecls []),+ Match loc f [ PWildCard ] Nothing (UnGuardedRhs (List [])) (BDecls [])+ ]]) (App (App (Var (UnQual (Ident "concatMap"))) (Var (UnQual f))) e2))+desugarListComp e (QualStmt (Qualifier e2) : stmts) = do+ nested <- desugarListComp e stmts+ return (If e2 nested (List []))+desugarListComp e (QualStmt (LetStmt bs) : stmts) = do+ nested <- desugarListComp e stmts+ return (Let bs nested)+desugarListComp _ (s : _ ) =+ throwError (UnsupportedQualStmt s)++-- | Make a Fay list.+makeList :: [JsExp] -> JsExp+makeList exps = (JsApp (JsName (JsBuiltIn "list")) [JsList exps])++-- | Compile a statement of a do block.+compileStmt :: Maybe Exp -> Stmt -> Compile (Maybe Exp)+compileStmt inner stmt =+ case inner of+ Nothing -> initStmt+ Just inner -> subsequentStmt inner++ where initStmt =+ case stmt of+ Qualifier exp -> return (Just exp)+ LetStmt{} -> throwError LetUnsupported+ _ -> throwError InvalidDoBlock++ subsequentStmt inner =+ case stmt of+ Generator loc pat exp -> compileGenerator loc pat inner exp+ Qualifier exp -> return (Just (InfixApp exp+ (QVarOp (UnQual (Symbol ">>")))+ inner))+ LetStmt (BDecls binds) -> return (Just (Let (BDecls binds) inner))+ LetStmt _ -> throwError LetUnsupported+ RecStmt{} -> throwError RecursiveDoUnsupported++ compileGenerator srcloc pat inner exp = do+ let body = Lambda srcloc [pat] inner+ return (Just (InfixApp exp+ (QVarOp (UnQual (Symbol ">>=")))+ body))++-- | Optimize short literal [e1..e3] arithmetic sequences.+optEnumFromTo :: CompileConfig -> JsExp -> JsExp -> Maybe JsExp+optEnumFromTo cfg (JsLit f) (JsLit t) =+ if configOptimize cfg+ then case (f,t) of+ (JsInt fl, JsInt tl) -> strict JsInt fl tl+ (JsFloating fl, JsFloating tl) -> strict JsFloating fl tl+ _ -> Nothing+ else Nothing+ where strict :: (Enum a, Ord a, Num a) => (a -> JsLit) -> a -> a -> Maybe JsExp+ strict litfn f t =+ if fromEnum t - fromEnum f < maxStrictASLen+ then Just . makeList . map (JsLit . litfn) $ enumFromTo f t+ else Nothing+optEnumFromTo _ _ _ = Nothing++-- | Optimize short literal [e1,e2..e3] arithmetic sequences.+optEnumFromThenTo :: CompileConfig -> JsExp -> JsExp -> JsExp -> Maybe JsExp+optEnumFromThenTo cfg (JsLit fr) (JsLit th) (JsLit to) =+ if configOptimize cfg+ then case (fr,th,to) of+ (JsInt frl, JsInt thl, JsInt tol) -> strict JsInt frl thl tol+ (JsFloating frl, JsFloating thl, JsFloating tol) -> strict JsFloating frl thl tol+ _ -> Nothing+ else Nothing+ where strict :: (Enum a, Ord a, Num a) => (a -> JsLit) -> a -> a -> a -> Maybe JsExp+ strict litfn fr th to =+ if (fromEnum to - fromEnum fr) `div`+ (fromEnum th - fromEnum fr) + 1 < maxStrictASLen+ then Just . makeList . map (JsLit . litfn) $ enumFromThenTo fr th to+ else Nothing+optEnumFromThenTo _ _ _ _ = Nothing++-- | Maximum number of elements to allow in strict list representation+-- of arithmetic sequences.+maxStrictASLen :: Int+maxStrictASLen = 10
+ src/Fay/Compiler/FFI.hs view
@@ -0,0 +1,357 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS -Wall #-}++-- | Compiling the FFI support.++module Fay.Compiler.FFI+ (emitFayToJs+ ,emitJsToFay+ ,compileFFI+ ,jsToFayDispatcher+ ,fayToJsDispatcher)+ where++import Fay.Compiler.Misc+import Fay.Compiler.Print (printJSString)+import Fay.Types++import Control.Monad.Error+import Control.Monad.Writer+import Data.Char+import Data.Generics.Schemes+import Data.List+import Data.Maybe+import Data.String+import Language.ECMAScript3.Parser as JS+import Language.ECMAScript3.Syntax+import Language.Haskell.Exts (prettyPrint)+import Language.Haskell.Exts.Syntax+import Prelude hiding (exp)+import Safe++-- | Compile an FFI call.+compileFFI :: SrcLoc -- ^ Location of the original FFI decl.+ -> Name -- ^ Name of the to-be binding.+ -> String -- ^ The format string.+ -> Type -- ^ Type signature.+ -> Compile [JsStmt]+compileFFI srcloc name formatstr sig = do+ inner <- formatFFI formatstr (zip params funcFundamentalTypes)+ case JS.parse JS.parseExpression (prettyPrint name) (printJSString (wrapReturn inner)) of+ Left err -> throwError (FfiFormatInvalidJavaScript srcloc inner (show err))+ Right exp -> do+ config' <- config id+ when (configGClosure config') $ warnDotUses srcloc inner exp+ fmap return (bindToplevel srcloc True name (body inner))++ where body inner = foldr wrapParam (wrapReturn inner) params+ wrapParam pname inner = JsFun [pname] [] (Just inner)+ params = zipWith const uniqueNames [1..typeArity sig]+ wrapReturn inner = thunk $+ case lastMay funcFundamentalTypes of+ -- Returns a “pure” value;+ Just{} -> jsToFay SerializeAnywhere returnType (JsRawExp inner)+ -- Base case:+ Nothing -> JsRawExp inner+ funcFundamentalTypes = functionTypeArgs sig+ returnType = last funcFundamentalTypes++-- | Warn about uses of naked x.y which will not play nicely with Google Closure.+warnDotUses :: SrcLoc -> String -> ParsedExpression -> Compile ()+warnDotUses srcloc string expr =+ when anyrefs $+ warn $ printSrcLoc srcloc ++ ":\nDot ref syntax used in FFI JS code: " ++ string++ where anyrefs = not (null (listify dotref expr)) ||+ not (null (listify ldot expr))++ dotref :: ParsedExpression -> Bool+ dotref x = case x of+ DotRef _ (VarRef _ (Id _ name)) _+ | elem name globalNames -> False+ DotRef{} -> True+ _ -> False++ ldot :: LValue SourcePos -> Bool+ ldot x =+ case x of+ LDot _ (VarRef _ (Id _ name)) _+ | elem name globalNames -> False+ LDot{} -> True+ _ -> False++ globalNames = ["Math","console","JSON"]++-- | Make a Fay→JS encoder.+emitFayToJs :: Name -> [([Name],BangType)] -> Compile ()+emitFayToJs name (explodeFields -> fieldTypes) = do+ qname <- qualify name+ tell (mempty { writerFayToJs = [translator qname] })++ where+ translator qname =+ JsIf (JsInstanceOf (JsName transcodingObjForced) (JsConstructor qname))+ (obj : fieldStmts (zip [0..] fieldTypes) ++ [ret])+ []++ obj :: JsStmt+ obj = JsVar obj_ $+ JsObj [("instance",JsLit (JsStr (printJSString name)))]++ fieldStmts :: [(Int,(Name,BangType))] -> [JsStmt]+ fieldStmts [] = []+ fieldStmts ((i,fieldType):fts) =+ (JsVar obj_v field) :+ (JsIf (JsNeq JsUndefined (JsName obj_v))+ [JsSetPropExtern obj_ decl (JsName obj_v)]+ []) :+ fieldStmts fts+ where+ obj_v = JsNameVar (UnQual (Ident $ "obj_" ++ d))+ decl = JsNameVar (UnQual (Ident d))+ (d, field) = declField i fieldType++ obj_ = JsNameVar (UnQual (Ident "obj_"))++ ret :: JsStmt+ ret = JsEarlyReturn (JsName obj_)++ -- Declare/encode Fay→JS field+ declField :: Int -> (Name,BangType) -> (String,JsExp)+ declField i (fname,typ) =+ (prettyPrint fname+ ,fayToJs (SerializeUserArg i)+ (argType (bangType typ))+ (JsGetProp (JsName transcodingObjForced)+ (JsNameVar (UnQual fname))))++-- | A name used for transcoding.+transcodingObj :: JsName+transcodingObj = JsNameVar "obj"++-- | The name used for the forced version of a transcoding variable.+transcodingObjForced :: JsName+transcodingObjForced = JsNameVar "_obj"++-- | Get arg types of a function type.+functionTypeArgs :: Type -> [FundamentalType]+functionTypeArgs t =+ case t of+ TyForall _ _ i -> functionTypeArgs i+ TyFun a b -> argType a : functionTypeArgs b+ TyParen st -> functionTypeArgs st+ r -> [argType r]++-- | Convert a Haskell type to an internal FFI representation.+argType :: Type -> FundamentalType+argType t = case t of+ TyCon "String" -> StringType+ TyCon "Double" -> DoubleType+ TyCon "Int" -> IntType+ TyCon "Bool" -> BoolType+ TyApp (TyCon "Ptr") _ -> PtrType+ TyApp (TyCon "Automatic") _ -> Automatic+ TyApp (TyCon "Defined") a -> Defined (argType a)+ TyApp (TyCon "Nullable") a -> Nullable (argType a)+ TyApp (TyCon "Fay") a -> JsType (argType a)+ TyFun x xs -> FunctionType (argType x : functionTypeArgs xs)+ TyList x -> ListType (argType x)+ TyTuple _ xs -> TupleType (map argType xs)+ TyParen st -> argType st+ TyApp op arg -> userDefined (reverse (arg : expandApp op))+ _ ->+ -- No semantic point to this, merely to avoid GHC's broken+ -- warning.+ case t of+ TyCon (UnQual user) -> UserDefined user []+ _ -> UnknownType++-- | Extract the type.+bangType :: BangType -> Type+bangType typ = case typ of+ BangedTy ty -> ty+ UnBangedTy ty -> ty+ UnpackedTy ty -> ty++-- | Expand a type application.+expandApp :: Type -> [Type]+expandApp (TyParen t) = expandApp t+expandApp (TyApp op arg) = arg : expandApp op+expandApp x = [x]++-- | Generate a user-defined type.+userDefined :: [Type] -> FundamentalType+userDefined (TyCon (UnQual name):typs) = UserDefined name (map argType typs)+userDefined _ = UnknownType++-- | Translate: JS → Fay.+jsToFay :: SerializeContext -> FundamentalType -> JsExp -> JsExp+jsToFay = translate "jsToFay"+-- | Translate: Fay → JS.+fayToJs :: SerializeContext -> FundamentalType -> JsExp -> JsExp+fayToJs = translate "fayToJs"++-- | Make a translator.+translate :: String -> SerializeContext -> FundamentalType -> JsExp -> JsExp+translate method context typ exp = case typ of+ -- Unserialized types+ PtrType -> exp+ -- Flat types+ StringType -> flat "string"+ DoubleType -> flat "double"+ IntType -> flat "int"+ BoolType -> flat "bool"+ -- Collapse monad+ JsType x | method == "jsToFay" -> js x+ -- Otherwise recursive stuff needs the big guns+ _ -> recursive++ where flat specialize =+ JsApp (JsName (JsBuiltIn (fromString (method ++ "_" ++ specialize))))+ [exp]+ recursive =+ JsApp (JsName (JsBuiltIn (fromString method)))+ [typeRep context typ+ ,exp]+ js ty' =+ JsNew (JsBuiltIn "Monad")+ [translate method context ty' exp]++-- | Get a JS-representation of a fundamental type for encoding/decoding.+typeRep :: SerializeContext -> FundamentalType -> JsExp+typeRep context typ = case typ of+ FunctionType xs -> JsList [JsLit $ JsStr "function",JsList (map (typeRep context) xs)]+ JsType x -> JsList [JsLit $ JsStr "action",JsList [typeRep context x]]+ ListType x -> JsList [JsLit $ JsStr "list",JsList [typeRep context x]]+ TupleType xs -> JsList [JsLit $ JsStr "tuple",JsList (map (typeRep context) xs)]+ UserDefined name xs -> JsList [JsLit $ JsStr "user"+ ,JsLit $ JsStr (unname name)+ ,JsList (zipWith (\t i -> typeRep (setArg i context) t) xs [0..])]+ Defined x -> JsList [JsLit $ JsStr "defined",JsList [typeRep context x]]+ Nullable x -> JsList [JsLit $ JsStr "nullable",JsList [typeRep context x]]+ _ -> nom++ where+ setArg i SerializeUserArg{} = SerializeUserArg i+ setArg _ c = c+ ret = JsList . return . JsLit . JsStr+ nom = case typ of+ StringType -> ret "string"+ DoubleType -> ret "double"+ PtrType -> ret "ptr"+ Automatic -> ret "automatic"+ IntType -> ret "int"+ BoolType -> ret "bool"+ DateType -> ret "date"+ _ ->+ case context of+ SerializeAnywhere -> ret "unknown"+ SerializeUserArg i ->+ let args = JsName argTypes+ automatic = JsIndex 0 (JsName JsParametrizedType)+ thisArg = JsIndex i args+ in JsTernaryIf (JsInfix "&&" args thisArg)+ thisArg+ (JsTernaryIf (JsEq automatic (JsLit "automatic"))+ (ret "automatic")+ (ret "unknown"))++-- | Get the arity of a type.+typeArity :: Type -> Int+typeArity t = case t of+ TyForall _ _ i -> typeArity i+ TyFun _ b -> 1 + typeArity b+ TyParen st -> typeArity st+ _ -> 0++-- | Format the FFI format string with the given arguments.+formatFFI :: String -- ^ The format string.+ -> [(JsName,FundamentalType)] -- ^ Arguments.+ -> Compile String -- ^ The JS code.+formatFFI formatstr args = go formatstr where+ go ('%':'*':xs) = do+ these <- mapM inject (zipWith const [1..] args)+ rest <- go xs+ return (intercalate "," these ++ rest)+ go ('%':'%':xs) = do+ rest <- go xs+ return ('%' : rest)+ go ['%'] = throwError FfiFormatIncompleteArg+ go ('%':(span isDigit -> (op,xs))) =+ case readMay op of+ Nothing -> throwError (FfiFormatBadChars op)+ Just n -> do+ this <- inject n+ rest <- go xs+ return (this ++ rest)+ go (x:xs) = do rest <- go xs+ return (x : rest)+ go [] = return []++ inject n =+ case listToMaybe (drop (n-1) args) of+ Nothing -> throwError (FfiFormatNoSuchArg n)+ Just (arg,typ) -> do+ return (printJSString (fayToJs SerializeAnywhere typ (JsName arg)))++-- | Generate n name-typ pairs from the given list.+explodeFields :: [([a], t)] -> [(a, t)]+explodeFields = concatMap $ \(names,typ) -> map (,typ) names++-- | The dispatcher for Fay->JS conversion.+fayToJsDispatcher :: [JsStmt] -> JsStmt+fayToJsDispatcher cases =+ JsVar (JsBuiltIn "fayToJsUserDefined")+ (JsFun [JsNameVar "type",transcodingObj]+ (decl ++ cases ++ [baseCase])+ Nothing)++ where decl = [JsVar transcodingObjForced+ (force (JsName transcodingObj))+ ,JsVar argTypes+ (JsLookup (JsName JsParametrizedType)+ (JsLit (JsInt 2)))]+ baseCase =+ JsEarlyReturn (JsName transcodingObj)++-- | The dispatcher for JS->Fay conversion.+jsToFayDispatcher :: [JsStmt] -> JsStmt+jsToFayDispatcher cases =+ JsVar (JsBuiltIn "jsToFayUserDefined")+ (JsFun [JsNameVar "type",transcodingObj]+ (decl ++ cases ++ [baseCase])+ Nothing)++ where baseCase =+ JsEarlyReturn (JsName transcodingObj)+ decl = [JsVar argTypes+ (JsLookup (JsName JsParametrizedType)+ (JsLit (JsInt 2)))]++-- | Make a JS→Fay decoder.+emitJsToFay :: Name -> [([Name], BangType)] -> Compile ()+emitJsToFay name (explodeFields -> fieldTypes) = do+ qname <- qualify name+ tell (mempty { writerJsToFay = [translator qname] })++ where+ translator qname =+ JsIf (JsEq (JsGetPropExtern (JsName transcodingObj) "instance")+ (JsLit (JsStr (printJSString name))))+ [JsEarlyReturn (JsNew (JsConstructor qname)+ (zipWith decodeField fieldTypes [0..]))]+ []+ -- Decode JS→Fay field+ decodeField :: (Name,BangType) -> Int -> JsExp+ decodeField (fname,typ) i =+ jsToFay (SerializeUserArg i)+ (argType (bangType typ))+ (JsGetPropExtern (JsName transcodingObj)+ (prettyPrint fname))++-- | The argument types used in serialization of parametrized user-defined types.+argTypes :: JsName+argTypes = JsNameVar "argTypes"
+ src/Fay/Compiler/Misc.hs view
@@ -0,0 +1,337 @@+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS -Wall -fno-warn-orphans #-}++-- | Miscellaneous functions used throughout the compiler.++module Fay.Compiler.Misc where++import qualified Fay.Compiler.ModuleScope as ModuleScope+import Fay.Types++import Control.Applicative+import Control.Monad.Error+import Control.Monad.IO+import Control.Monad.RWS+import Data.List+import Data.Maybe+import qualified Data.Set as S+import Data.String+import Data.Version (parseVersion)+import Language.Haskell.Exts.Syntax+import Language.Haskell.Exts.Parser+import Language.Haskell.Exts.Pretty+import Language.Haskell.Exts.Extension+import Prelude hiding (exp, mod)+import System.Directory+import System.FilePath+import System.IO+import System.Process (readProcess)+import Text.ParserCombinators.ReadP (readP_to_S)++-- | Extra the string from an ident.+unname :: Name -> String+unname (Ident str) = str+unname _ = error "Expected ident from uname." -- FIXME:++-- | Make an identifier from the built-in HJ module.+fayBuiltin :: String -> QName+fayBuiltin = Qual (ModuleName "Fay$") . Ident++-- | Wrap an expression in a thunk.+thunk :: JsExp -> JsExp+-- thunk exp = JsNew (fayBuiltin "Thunk") [JsFun [] [] (Just exp)]+thunk expr =+ case expr of+ -- JS constants don't need to be in thunks, they're already strict.+ JsLit{} -> expr+ -- Functions (e.g. lets) used for introducing a new lexical scope+ -- aren't necessary inside a thunk. This is a simple aesthetic+ -- optimization.+ JsApp fun@JsFun{} [] -> JsNew JsThunk [fun]+ -- Otherwise make a regular thunk.+ _ -> JsNew JsThunk [JsFun [] [] (Just expr)]++-- | Wrap an expression in a thunk.+stmtsThunk :: [JsStmt] -> JsExp+stmtsThunk stmts = JsNew JsThunk [JsFun [] stmts Nothing]++-- | Generate unique names.+uniqueNames :: [JsName]+uniqueNames = map JsParam [1::Integer ..]++-- | Resolve a given maybe-qualified name to a fully qualifed name.+resolveName :: QName -> Compile QName+resolveName special@Special{} = return special+resolveName q@Qual{} = do+ env <- gets stateModuleScope+ maybe (throwError $ UnableResolveQualified q) return (ModuleScope.resolveName q env)+resolveName u@(UnQual name) = do+ names <- gets stateLocalScope+ env <- gets stateModuleScope+ if S.member name names+ then return (UnQual name)+ else maybe (qualify name) return (ModuleScope.resolveName u env)++-- | Qualify a name for the current module.+qualify :: Name -> Compile QName+qualify name = do+ modulename <- gets stateModuleName+ return (Qual modulename name)++-- | Make a top-level binding.+bindToplevel :: SrcLoc -> Bool -> Name -> JsExp -> Compile JsStmt+bindToplevel srcloc toplevel name expr = do+ qname <- (if toplevel then qualify else return . UnQual) name+ return (JsMappedVar srcloc (JsNameVar qname) expr)++-- | Create a temporary environment and discard it after the given computation.+withModuleScope :: Compile a -> Compile a+withModuleScope m = do+ scope <- gets stateModuleScope+ value <- m+ modify $ \s -> s { stateModuleScope = scope }+ return value++-- | Create a temporary scope and discard it after the given computation.+withScope :: Compile a -> Compile a+withScope m = do+ scope <- gets stateLocalScope+ value <- m+ modify $ \s -> s { stateLocalScope = scope }+ return value++-- | Run a compiler and just get the scope information.+generateScope :: Compile a -> Compile ()+generateScope m = do+ st <- get+ _ <- m+ scope <- gets stateLocalScope+ put st { stateLocalScope = scope }++-- | Bind a variable in the current scope.+bindVar :: Name -> Compile ()+bindVar name = do+ modify $ \s -> s { stateLocalScope = S.insert name (stateLocalScope s) }++-- | Emit exported names.+emitExport :: ExportSpec -> Compile ()+emitExport spec = case spec of+ EVar (UnQual n) -> emitVar n+ EVar q@Qual{} -> modify $ addCurrentExport q+ EThingAll (UnQual name) -> do+ emitVar name+ r <- lookup (UnQual name) <$> gets stateRecords+ maybe (return ()) (mapM_ (emitVar . unQName)) r+ EThingWith (UnQual name) ns -> do+ emitVar name+ mapM_ emitCName ns+ EAbs _ -> return () -- Type only, skip+ EModuleContents mod ->+ mapM_ (emitExport . EVar) =<< ModuleScope.moduleLocals mod <$> gets stateModuleScope++ -- Skip qualified exports for type exports in fay-base since+ -- qualified imports are not supported yet an error will be thrown+ -- on the import so hopefully this won't be confusing.+ EThingAll (Qual _ _) -> return ()+ e -> do+ liftIO (print e)+ throwError $ UnsupportedExportSpec e+ where+ emitVar = return . UnQual >=> resolveName >=> emitExport . EVar+ emitCName (VarName n) = emitVar n+ emitCName (ConName n) = emitVar n+ unQName (UnQual u) = u+ unQName _ = error "unQName Qual or Special -- should never happen"++-- | Force an expression in a thunk.+force :: JsExp -> JsExp+force expr+ | isConstant expr = expr+ | otherwise = JsApp (JsName JsForce) [expr]++-- | Is a JS expression a literal (constant)?+isConstant :: JsExp -> Bool+isConstant JsLit{} = True+isConstant _ = False++-- | Deconstruct a parse result (a la maybe, foldr, either).+parseResult :: ((SrcLoc,String) -> b) -> (a -> b) -> ParseResult a -> b+parseResult die ok result = case result of+ ParseOk a -> ok a+ ParseFailed srcloc msg -> die (srcloc,msg)++-- | Get a config option.+config :: (CompileConfig -> a) -> Compile a+config f = asks (f . readerConfig)++-- | Optimize pattern matching conditions by merging conditions in common.+optimizePatConditions :: [[JsStmt]] -> [[JsStmt]]+optimizePatConditions = concatMap merge . groupBy sameIf where+ sameIf [JsIf cond1 _ _] [JsIf cond2 _ _] = cond1 == cond2+ sameIf _ _ = False+ merge xs@([JsIf cond _ _]:_) =+ [[JsIf cond (concat (optimizePatConditions (map getIfConsequent xs))) []]]+ merge noifs = noifs+ getIfConsequent [JsIf _ cons _] = cons+ getIfConsequent other = other++-- | Throw a JS exception.+throw :: String -> JsExp -> JsStmt+throw msg expr = JsThrow (JsList [JsLit (JsStr msg),expr])++-- | Throw a JS exception (in an expression).+throwExp :: String -> JsExp -> JsExp+throwExp msg expr = JsThrowExp (JsList [JsLit (JsStr msg),expr])++-- | Is an alt a wildcard?+isWildCardAlt :: Alt -> Bool+isWildCardAlt (Alt _ pat _ _) = isWildCardPat pat++-- | Is a pattern a wildcard?+isWildCardPat :: Pat -> Bool+isWildCardPat PWildCard{} = True+isWildCardPat PVar{} = True+isWildCardPat _ = False++-- | Generate a temporary, SCOPED name for testing conditions and+-- such.+withScopedTmpJsName :: (JsName -> Compile a) -> Compile a+withScopedTmpJsName withName = do+ depth <- gets stateNameDepth+ modify $ \s -> s { stateNameDepth = depth + 1 }+ ret <- withName $ JsTmp depth+ modify $ \s -> s { stateNameDepth = depth }+ return ret++-- | Generate a temporary, SCOPED name for testing conditions and+-- such. We don't have name tracking yet, so instead we use this.+withScopedTmpName :: (Name -> Compile a) -> Compile a+withScopedTmpName withName = do+ depth <- gets stateNameDepth+ modify $ \s -> s { stateNameDepth = depth + 1 }+ ret <- withName $ Ident $ "$gen" ++ show depth+ modify $ \s -> s { stateNameDepth = depth }+ return ret++-- | Print out a compiler warning.+warn :: String -> Compile ()+warn "" = return ()+warn w = do+ shouldWarn <- config configWarn+ when shouldWarn . liftIO . hPutStrLn stderr $ "Warning: " ++ w++-- | Pretty print a source location.+printSrcLoc :: SrcLoc -> String+printSrcLoc SrcLoc{..} = srcFilename ++ ":" ++ show srcLine ++ ":" ++ show srcColumn++-- | Lookup the record for a given type name.+typeToRecs :: QName -> Compile [QName]+typeToRecs typ = fromMaybe [] . lookup typ <$> gets stateRecordTypes++-- | Get the fields for a given type.+typeToFields :: QName -> Compile [QName]+typeToFields typ = do+ allrecs <- gets stateRecords+ typerecs <- typeToRecs typ+ return . concatMap snd . filter ((`elem` typerecs) . fst) $ allrecs++-- | Get the flag used for GHC, this differs between GHC-7.6.0 and+-- GHC-everything-else so we need to specially test for that. It's+-- lame, but that's random flag name changes for you.+getGhcPackageDbFlag :: IO String+getGhcPackageDbFlag = do+ s <- readProcess "ghc" ["--version"] ""+ return $+ case (mapMaybe readVersion $ words s, readVersion "7.6.0") of+ (v:_, Just min') | v > min' -> "-package-db"+ _ -> "-package-conf"+ where+ readVersion = listToMaybe . filter (null . snd) . readP_to_S parseVersion++-- | Find an import's filepath and contents from its module name.+findImport :: [FilePath] -> ModuleName -> Compile (FilePath,String)+findImport alldirs mname = go alldirs mname where+ go (dir:dirs) name = do+ exists <- io (doesFileExist path)+ if exists+ then fmap (path,) (fmap stdlibHack (io (readFile path)))+ else go dirs name+ where+ path = dir </> replace '.' '/' (prettyPrint name) ++ ".hs"+ replace c r = map (\x -> if x == c then r else x)+ go [] name =+ throwError $ Couldn'tFindImport name alldirs++ stdlibHack+ | mname == ModuleName "Language.Fay.Stdlib" = \s -> s ++ "\n\ndata Maybe a = Just a | Nothing"+ | mname == ModuleName "Language.Fay.FFI" = const "module Language.Fay.FFI where\n\ndata Nullable a = Nullable a | Null\n\ndata Defined a = Defined a | Undefined"+ | otherwise = id++-- | Convert a GADT to a normal data type.+convertGADT :: GadtDecl -> QualConDecl+convertGADT d =+ case d of+ GadtDecl srcloc name typ -> QualConDecl srcloc tyvars context+ (ConDecl name (convertFunc typ))+ where tyvars = []+ context = []+ convertFunc (TyCon _) = []+ convertFunc (TyFun x xs) = UnBangedTy x : convertFunc xs+ convertFunc (TyParen x) = convertFunc x+ convertFunc _ = []++-- | Run the compiler.+runCompile :: CompileReader -> CompileState+ -> Compile a+ -> IO (Either CompileError (a,CompileState,CompileWriter))+runCompile reader' state' m = runErrorT (runRWST (unCompile m) reader' state')++-- | Parse some Fay code.+parseFay :: Parseable ast => FilePath -> String -> ParseResult ast+parseFay filepath = parseWithMode parseMode { parseFilename = filepath } . applyCPP++-- | Apply incredibly simplistic CPP handling. It only recognizes the following:+--+-- > #if FAY+-- > #ifdef FAY+-- > #ifndef FAY+-- > #else+-- > #endif+--+-- Note that this implementation replaces all removed lines with blanks, so+-- that line numbers remain accurate.+applyCPP :: String -> String+applyCPP =+ unlines . loop NoCPP . lines+ where+ loop _ [] = []+ loop state' ("#if FAY":rest) = "" : loop (CPPIf True state') rest+ loop state' ("#ifdef FAY":rest) = "" : loop (CPPIf True state') rest+ loop state' ("#ifndef FAY":rest) = "" : loop (CPPIf False state') rest+ loop (CPPIf b oldState') ("#else":rest) = "" : loop (CPPElse (not b) oldState') rest+ loop (CPPIf _ oldState') ("#endif":rest) = "" : loop oldState' rest+ loop (CPPElse _ oldState') ("#endif":rest) = "" : loop oldState' rest+ loop state' (x:rest) = (if toInclude state' then x else "") : loop state' rest++ toInclude NoCPP = True+ toInclude (CPPIf x state') = x && toInclude state'+ toInclude (CPPElse x state') = x && toInclude state'++-- | The CPP's parsing state.+data CPPState = NoCPP+ | CPPIf Bool CPPState+ | CPPElse Bool CPPState++-- | The parse mode for Fay.+parseMode :: ParseMode+parseMode = defaultParseMode+ { extensions = [GADTs+ ,StandaloneDeriving+ ,PackageImports+ ,EmptyDataDecls+ ,TypeOperators+ ,RecordWildCards+ ,NamedFieldPuns]+ }
+ src/Fay/Compiler/ModuleScope.hs view
@@ -0,0 +1,140 @@+{-# LANGUAGE OverloadedStrings #-}++-- | Handles variable bindings on the module level and also keeps track of+-- primitive operations that we want to treat specially.++module Fay.Compiler.ModuleScope+ (ModuleScope+ ,bindAsLocals+ ,findTopLevelNames+ ,resolveName+ ,moduleLocals)+ where++import Control.Arrow+import Control.Monad.Reader+import Control.Monad.Writer+import Data.Default+import Data.Map (Map)+import qualified Data.Map as M+import Language.Haskell.Exts hiding (name, binds)+import Prelude hiding (mod)++-- | Maps names bound in the module to their real names+-- The keys are unqualified for locals and imports,+-- the values are always fully qualified+-- Example contents:+-- [ (UnQUal "main" , Qual "Main" "main")+-- , (UnQual "take" , Qual "Prelude" "take")+-- , ( Qual "M" "insertWith", Qual "Data.Map" "insertWith") ]+newtype ModuleScope = ModuleScope (Map QName QName)+ deriving Show++instance Monoid ModuleScope where+ mempty = ModuleScope M.empty+ mappend (ModuleScope a) (ModuleScope b) = ModuleScope $ a `M.union` b++instance Default ModuleScope where+ def = mempty++-- | Find the path of a locally bound name+-- Returns special values in the "Fay$" module for primOps+resolveName :: QName -> ModuleScope -> Maybe QName+resolveName q (ModuleScope binds) = case M.lookup q binds of -- lookup in the module environment.++ -- something pointing to prelude, is it a primop?+ Just q'@(Qual (ModuleName "Prelude") n) -> case M.lookup n envPrimOpsMap of+ Just x -> Just x -- A primop which looks like it's imported from prelude.+ Nothing -> Just q' -- Regular prelude import, leave it as is.++ -- No matches in the current environment, so it may be a primop if it's unqualified.+ -- If Nothing is returned from either of the branches it means that there is+ -- no primop and nothing in env scope so GHC would have given an error.+ Nothing -> case q of+ UnQual n -> M.lookup n envPrimOpsMap+ _ -> Nothing+ j -> j -- Non-prelude import that was found in the env++-- | Bind a list of names into the local scope+-- Right now all bindings are made unqualified+bindAsLocals :: [QName] -> ModuleScope -> ModuleScope+bindAsLocals qs (ModuleScope binds) =+ -- This needs to be changed to not use unqual to support qualified imports.+ ModuleScope $ M.fromList (map (unqual &&& id) qs) `M.union` binds+ where unqual (Qual _ n) = (UnQual n)+ unqual u@UnQual{} = u+ unqual Special{} = error "fay: ModuleScope.bindAsLocals: Special"++-- | Find all names that are bound locally in this module, which excludes imports.+moduleLocals :: ModuleName -> ModuleScope -> [QName]+moduleLocals mod (ModuleScope binds) = filter isLocal . M.elems $ binds+ where+ isLocal (Qual m _) = mod == m+ isLocal _ = False++--------------------------------------------------------------------------------+-- Primitive Operations++-- | The built-in operations that aren't actually compiled from+-- anywhere, they come from runtime.js.+--+-- They're in the names list so that they can be overriden by the user+-- in e.g. let a * b = a - b in 1 * 2.+--+-- So we resolve them to Fay$, i.e. the prefix used for the runtime+-- support. $ is not allowed in Haskell module names, so there will be+-- no conflicts if a user decicdes to use a module named Fay.+--+-- So e.g. will compile to (*) Fay$$mult, which is in runtime.js.+envPrimOpsMap :: Map Name QName+envPrimOpsMap = M.fromList+ [ (Symbol ">>", (Qual (ModuleName "Fay$") (Ident "then")))+ , (Symbol ">>=", (Qual (ModuleName "Fay$") (Ident "bind")))+ , (Ident "return", (Qual (ModuleName "Fay$") (Ident "return")))+ , (Ident "force", (Qual (ModuleName "Fay$") (Ident "force")))+ , (Ident "seq", (Qual (ModuleName "Fay$") (Ident "seq")))+ , (Symbol "*", (Qual (ModuleName "Fay$") (Ident "mult")))+ , (Symbol "+", (Qual (ModuleName "Fay$") (Ident "add")))+ , (Symbol "-", (Qual (ModuleName "Fay$") (Ident "sub")))+ , (Symbol "/", (Qual (ModuleName "Fay$") (Ident "divi")))+ , (Symbol "==", (Qual (ModuleName "Fay$") (Ident "eq")))+ , (Symbol "/=", (Qual (ModuleName "Fay$") (Ident "neq")))+ , (Symbol ">", (Qual (ModuleName "Fay$") (Ident "gt")))+ , (Symbol "<", (Qual (ModuleName "Fay$") (Ident "lt")))+ , (Symbol ">=", (Qual (ModuleName "Fay$") (Ident "gte")))+ , (Symbol "<=", (Qual (ModuleName "Fay$") (Ident "lte")))+ , (Symbol "&&", (Qual (ModuleName "Fay$") (Ident "and")))+ , (Symbol "||", (Qual (ModuleName "Fay$") (Ident "or")))+ ]++--------------------------------------------------------------------------------+-- AST++type ModuleScopeSt = ReaderT ModuleName (Writer ModuleScope) ()++-- | Get module level names from a haskell module AST.+findTopLevelNames :: ModuleName -> [Decl] -> ModuleScope+findTopLevelNames mod decls = snd . runWriter $ runReaderT (mapM_ d_decl decls) mod++bindName :: Name -> ModuleScopeSt+bindName k = ask >>= \mod -> tell (ModuleScope $ M.singleton (UnQual k) (Qual mod k))++d_decl :: Decl -> ModuleScopeSt+d_decl d = case d of+ DataDecl _ _ _ _ _ dd _ -> mapM_ d_qualCon dd+ PatBind _ (PVar n) _ _ _ -> bindName n+ FunBind (Match _ n _ _ _ _ : _) -> bindName n+ ClassDecl _ _ _ _ _ cds -> mapM_ d_classDecl cds+ TypeSig _ ns _ -> mapM_ bindName ns+ _ -> return ()++d_classDecl :: ClassDecl -> ModuleScopeSt+d_classDecl cd = case cd of+ ClsDecl d -> d_decl d+ _ -> return ()++d_qualCon :: QualConDecl -> ModuleScopeSt+d_qualCon (QualConDecl _ _ _ cd) = case cd of+ ConDecl n _ -> bindName n+ InfixConDecl _ n _ -> bindName n+ RecDecl n ns -> bindName n >> mapM_ bindName (concatMap fst ns)
+ src/Fay/Compiler/Optimizer.hs view
@@ -0,0 +1,268 @@+{-# OPTIONS -fno-warn-orphans #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE OverloadedStrings #-}++-- | Optimizing the outputted JavaScript(-ish) AST.++module Fay.Compiler.Optimizer where++import Fay.Compiler.Misc++import Control.Applicative+import Control.Arrow (first)+import Control.Monad.Error+import Control.Monad.Writer+import Control.Monad.State+import Data.List+import Data.Maybe+import Fay.Types+import Language.Haskell.Exts (QName(..),ModuleName(..),Name(..))++import Prelude hiding (exp)++-- | The arity of a function. Arity here is defined to be the number+-- of arguments that can be directly uncurried from a curried lambda+-- abstraction. So \x y z -> if x then (\a -> a) else (\a -> a) has an+-- arity of 3, not 4.+type FuncArity = (QName,Int)++-- | Optimize monad.+type Optimize = State OptState++-- | State.+data OptState = OptState+ { optStmts :: [JsStmt]+ , optUncurry :: [QName]+ }++-- | Run an optimizer, which may output additional statements.+runOptimizer :: ([JsStmt] -> Optimize [JsStmt]) -> [JsStmt] -> [JsStmt]+runOptimizer optimizer stmts =+ let (newstmts,OptState _ uncurried) = flip runState st $ optimizer stmts+ in (newstmts ++ (tco (catMaybes (map (uncurryBinding newstmts) (nub uncurried)))))+ where st = OptState stmts []++-- | Inline x >> y to x;y in the JS output.+inlineMonad :: [JsStmt] -> [JsStmt]+inlineMonad = map go where+ go stmt =+ case stmt of+ JsVar name exp -> JsVar name (inline exp)+ JsMappedVar a name exp -> JsMappedVar a name (inline exp)+ JsIf exp stmts stmts' -> JsIf (inline exp) (map go stmts) (map go stmts')+ JsEarlyReturn exp -> JsEarlyReturn (inline exp)+ JsThrow exp -> JsThrow (inline exp)+ JsWhile exp stmts -> JsWhile (inline exp) (map go stmts)+ JsUpdate name exp -> JsUpdate name (inline exp)+ JsSetProp a b exp -> JsSetProp a b (inline exp)+ JsSetPropExtern a b exp -> JsSetPropExtern a b (inline exp)+ JsContinue -> JsContinue+ JsBlock stmts -> JsBlock (map go stmts)++ inline expr =+ case expr of+ -- Optimizations+ JsApp op args -> case flatten expr of+ Nothing -> JsApp (inline op) (map inline args)+ Just x -> x++ -- Plumbing+ JsFun names stmts mexp -> JsFun names (map go stmts) (fmap inline mexp)++ JsNegApp exp -> JsNegApp (inline exp)+ JsTernaryIf exp1 exp2 exp3 -> JsTernaryIf (inline exp1) (inline exp2) (inline exp3)+ JsParen exp -> JsParen (inline exp)+ JsGetProp exp name -> JsGetProp (inline exp) name+ JsLookup exp exp2 -> JsLookup (inline exp) (inline exp2)+ JsUpdateProp exp name exp2 -> JsUpdateProp (inline exp) name (inline exp2)+ JsGetPropExtern exp string -> JsGetPropExtern (inline exp) string+ JsUpdatePropExtern exp name exp2 -> JsUpdatePropExtern (inline exp) name (inline exp2)+ JsList exps -> JsList (map inline exps)+ JsNew name exps -> JsNew name (map inline exps)+ JsThrowExp exp -> JsThrowExp (inline exp)+ JsInstanceOf exp name -> JsInstanceOf (inline exp) name+ JsIndex i exp -> JsIndex i (inline exp)+ JsEq exp exp2 -> JsEq (inline exp) (inline exp2)+ JsNeq exp exp2 -> JsNeq (inline exp) (inline exp2)+ JsInfix string exp exp2 -> JsInfix string (inline exp) (inline exp2)+ JsObj keyvals -> JsObj keyvals+ rest -> rest++-- | Flatten a a>>(b>>c) to [a,b,c].+flatten :: JsExp -> Maybe JsExp+flatten exp = case collect exp of+ Just (stmts@(_:_:_)) -> let s = reverse stmts+ in Just $ thunk (JsSeq (map force (init s) ++ [last s]))+ _ -> Nothing++-- | Try to collect nested a>>(b>>c).+collect :: JsExp -> Maybe [JsExp]+collect exp =+ case exp of+ JsApp op args | isThen op -> do+ case args of+ [rest,x] -> do xs <- collect rest+ return (x : xs)+ [x] -> return [x]+ _ -> Nothing+ _ -> return [exp]++ where isThen = (== JsName (JsNameVar (Qual (ModuleName "Fay$") (Ident "then$uncurried"))))++-- | Perform any top-level cross-module optimizations and GO DEEP to+-- optimize further.+optimizeToplevel :: [JsStmt] -> Optimize [JsStmt]+optimizeToplevel = stripAndUncurry++-- | Perform tail-call optimization.+tco :: [JsStmt] -> [JsStmt]+tco = map inStmt where+ inStmt stmt = case stmt of+ JsMappedVar srcloc name exp -> JsMappedVar srcloc name (inject name exp)+ JsVar name exp -> JsVar name (inject name exp)+ e -> e+ inject name exp = case exp of+ JsFun params [] (Just (JsNew JsThunk [JsFun [] stmts ret])) ->+ JsFun params+ []+ (Just+ (JsNew JsThunk+ [JsFun []+ (optimize params name (stmts ++ [ JsEarlyReturn e | Just e <- [ret] ]))+ Nothing]))+ _ -> exp+ optimize params name stmts = result where+ result = let (newstmts,w) = runWriter makeWhile+ in if null w+ then stmts+ else newstmts+ makeWhile = do+ newstmts <- fmap concat (mapM swap stmts)+ return [JsWhile (JsLit (JsBool True)) newstmts]+ swap stmt = case stmt of+ JsEarlyReturn e+ | tailCall e -> do tell [()]+ return (rebind e ++ [JsContinue])+ | otherwise -> return [stmt]+ JsIf p ithen ielse -> do+ newithen <- fmap concat (mapM swap ithen)+ newielse <- fmap concat (mapM swap ielse)+ return [JsIf p newithen newielse]+ e -> return [e]+ tailCall (JsApp (JsName cname) _) = cname == name+ tailCall _ = False+ rebind (JsApp _ args) = zipWith go args params where+ go arg param = JsUpdate param arg+ rebind e = error . show $ e++-- | Strip redundant forcing from the whole generated code.+stripAndUncurry :: [JsStmt] -> Optimize [JsStmt]+stripAndUncurry = applyToExpsInStmts stripFuncForces where+ stripFuncForces arities exp = case exp of+ JsApp (JsName JsForce) [JsName (JsNameVar f)]+ | Just _ <- lookup f arities -> return (JsName (JsNameVar f))+ JsFun ps stmts body -> do substmts <- mapM stripInStmt stmts+ sbody <- maybe (return Nothing) (fmap Just . go) body+ return (JsFun ps substmts sbody)+ JsApp a b -> do+ result <- walkAndStripForces arities exp+ case result of+ Just strippedExp -> go strippedExp+ Nothing -> JsApp <$> go a <*> mapM go b+ JsNegApp e -> JsNegApp <$> go e+ JsTernaryIf a b c -> JsTernaryIf <$> go a <*> go b <*> go c+ JsParen e -> JsParen <$> go e+ JsUpdateProp e n a -> JsUpdateProp <$> go e <*> pure n <*> go a+ JsList xs -> JsList <$> mapM go xs+ JsEq a b -> JsEq <$> go a <*> go b+ JsInfix op a b -> JsInfix op <$> go a <*> go b+ JsObj xs -> JsObj <$> mapM (\(x,y) -> (x,) <$> go y) xs+ JsNew name xs -> JsNew name <$> mapM go xs+ e -> return e++ where+ go = stripFuncForces arities+ stripInStmt = applyToExpsInStmt arities stripFuncForces++-- | Strip redundant forcing from an application if possible.+walkAndStripForces :: [FuncArity] -> JsExp -> Optimize (Maybe JsExp)+walkAndStripForces arities = go True [] where+ go frst args app = case app of+ JsApp (JsName JsForce) [e] -> if frst+ then do result <- go False args e+ case result of+ Nothing -> return Nothing+ Just ex -> return (Just (JsApp (JsName JsForce) [ex]))+ else go False args e+ JsApp op [arg] -> go False (arg:args) op+ JsName (JsNameVar f)+ | Just arity <- lookup f arities, length args == arity -> do+ modify $ \s -> s { optUncurry = f : optUncurry s }+ return (Just (JsApp (JsName (JsNameVar (renameUncurried f))) args))+ _ -> return Nothing++-- | Apply the given function to the top-level expressions in the+-- given statements.+applyToExpsInStmts :: ([FuncArity] -> JsExp -> Optimize JsExp) -> [JsStmt] -> Optimize [JsStmt]+applyToExpsInStmts f stmts = mapM (applyToExpsInStmt (collectFuncs stmts) f) stmts++-- | Apply the given function to the top-level expressions in the+-- given statement.+applyToExpsInStmt :: [FuncArity] -> ([FuncArity] -> JsExp -> Optimize JsExp) -> JsStmt -> Optimize JsStmt+applyToExpsInStmt funcs f stmts = uncurryInStmt stmts where+ transform = f funcs+ uncurryInStmt stmt = case stmt of+ JsMappedVar srcloc name exp -> JsMappedVar srcloc name <$> transform exp+ JsVar name exp -> JsVar name <$> transform exp+ JsEarlyReturn exp -> JsEarlyReturn <$> transform exp+ JsIf op ithen ielse -> JsIf <$> transform op+ <*> mapM uncurryInStmt ithen+ <*> mapM uncurryInStmt ielse+ s -> pure s++-- | Collect functions and their arity from the whole codeset.+collectFuncs :: [JsStmt] -> [FuncArity]+collectFuncs = (++ prim) . concat . map collectFunc where+ collectFunc (JsMappedVar _ name exp) = collectFunc (JsVar name exp)+ collectFunc (JsVar (JsNameVar name) exp) | arity > 0 = [(name,arity)]+ where arity = expArity exp+ collectFunc _ = []+ prim = map (first (Qual (ModuleName "Fay$"))) (unary ++ binary)+ unary = map (,1) [Ident "return"]+ binary = map ((,2) . Ident)+ ["then","bind","mult","mult","add","sub","div"+ ,"eq","neq","gt","lt","gte","lte","and","or"]++-- | Get the arity of an expression.+expArity :: JsExp -> Int+expArity (JsFun _ _ mexp) = 1 + maybe 0 expArity mexp+expArity _ = 0++-- | Change foo(x)(y) to foo$uncurried(x,y).+uncurryBinding :: [JsStmt] -> QName -> Maybe JsStmt+uncurryBinding stmts qname = listToMaybe (mapMaybe funBinding stmts)+ where+ funBinding stmt = case stmt of+ JsMappedVar srcloc (JsNameVar name) body+ | name == qname -> JsMappedVar srcloc (JsNameVar (renameUncurried name)) <$> uncurryIt body+ JsVar (JsNameVar name) body+ | name == qname -> JsVar (JsNameVar (renameUncurried name)) <$> uncurryIt body+ _ -> Nothing++ uncurryIt = Just . go [] where+ go args exp = case exp of+ JsFun [arg] [] (Just body) -> go (arg : args) body+ inner -> JsFun (reverse args) [] (Just inner)++-- | Rename an uncurried copy of a curried function.+renameUncurried :: QName -> QName+renameUncurried q = case q of+ Qual m n -> Qual m (renameUnQual n)+ UnQual n -> UnQual (renameUnQual n)+ s -> s+ where+ renameUnQual n = case n of+ Ident nom -> Ident (nom ++ postfix)+ Symbol nom -> Symbol (nom ++ postfix)+ postfix = "$uncurried"
+ src/Fay/Compiler/Packages.hs view
@@ -0,0 +1,76 @@+{-# LANGUAGE TupleSections #-}++-- | Dealing with Cabal packages in Fay's own special way.++module Fay.Compiler.Packages where++import Fay.Types+import Fay.Compiler.Config++import Control.Monad+import Data.List+import Data.Version+import GHC.Paths+import Paths_fay+import System.Directory+import System.FilePath+import System.Process.Extra++-- | Given a configuration, resolve any packages specified to their+-- data file directories for importing the *.hs sources.+resolvePackages :: CompileConfig -> IO CompileConfig+resolvePackages config = do+ foldM resolvePackage config (configPackages config)++-- | Resolve package.+resolvePackage :: CompileConfig -> String -> IO CompileConfig+resolvePackage config name = do+ desc <- describePackage (configPackageConf config) name+ case packageVersion desc of+ Nothing -> error $ "unable to find package version: " ++ name+ Just ver -> do+ let nameVer = name ++ "-" ++ ver+ shareDir <- fmap ($ nameVer) getShareGen+ let includes = [shareDir,shareDir </> "src"]+ exists <- mapM doesSourceDirExist includes+ if any id exists+ then return (addConfigDirectoryIncludes (map (Just nameVer,) includes) config)+ else error $ "unable to find (existing) package's share dir: " ++ name ++ "\n" +++ "tried: " ++ unlines includes ++ "\n" +++ "but none of them seem to have Haskell files in them."++-- | Does a directory exist and does it contain any Haskell sources?+doesSourceDirExist :: FilePath -> IO Bool+doesSourceDirExist path = do+ exists <- doesDirectoryExist path+ if not exists+ then return False+ else do files <- getDirectoryContents path+ return $ any ((==".hs") . takeExtension) files++-- | Describe the given package.+describePackage :: Maybe FilePath -> String -> IO String+describePackage db name = do+ result <- readAllFromProcess ghc_pkg args ""+ case result of+ Left err -> error $ "ghc-pkg describe error:\n" ++ err+ Right (_err,out) -> return out++ where args = concat [["describe",name]+ ,["-f" ++ db' | Just db' <- [db]]]++-- | Get the package version from the package description.+packageVersion :: String -> Maybe String+packageVersion = fmap (dropWhile (==' ')) . lookup "version:" . map (span (/=' ')) . lines++-- | Make a share directory generator.+getShareGen :: IO (String -> FilePath)+getShareGen = do+ dataDir <- getDataDir+ return $ \pkg ->+ joinPath (map (replace pkg . dropTrailingPathSeparator) (splitPath dataDir))++ where replace pkg component+ | component == nameVer = pkg+ | otherwise = component+ nameVer = "fay-" ++ intercalate "." (map show (versionBranch version))
+ src/Fay/Compiler/Pattern.hs view
@@ -0,0 +1,162 @@+{-# OPTIONS -fno-warn-name-shadowing #-}+{-# LANGUAGE OverloadedStrings #-}++-- | Compile pattern matches.++module Fay.Compiler.Pattern where++import Fay.Compiler.Misc+import Fay.Types++import Control.Monad.Error+import Control.Monad.State+import Control.Monad.Reader+import Data.List+import Data.Maybe+import Language.Haskell.Exts++-- | Compile the given pattern against the given expression.+compilePat :: JsExp -> Pat -> [JsStmt] -> Compile [JsStmt]+compilePat exp pat body =+ case pat of+ PVar name -> compilePVar name exp body+ PApp cons pats -> compilePApp cons pats exp body+ PLit literal -> compilePLit exp literal body+ PParen pat -> compilePat exp pat body+ PWildCard -> return body+ pat@PInfixApp{} -> compileInfixPat exp pat body+ PList pats -> compilePList pats body exp+ PTuple pats -> compilePList pats body exp+ PAsPat name pat -> compilePAsPat exp name pat body+ PRec name pats -> compilePatFields exp name pats body+ pat -> throwError (UnsupportedPattern pat)++-- | Compile a pattern variable e.g. x.+compilePVar :: Name -> JsExp -> [JsStmt] -> Compile [JsStmt]+compilePVar name exp body = do+ bindVar name+ return $ JsVar (JsNameVar (UnQual name)) exp : body++-- | Compile a record field pattern.+compilePatFields :: JsExp -> QName -> [PatField] -> [JsStmt] -> Compile [JsStmt]+compilePatFields exp name pats body = do+ c <- liftM (++ body) (compilePats' [] pats)+ qname <- resolveName name+ return [JsIf (force exp `JsInstanceOf` JsConstructor qname) c []]+ where -- compilePats' collects field names that had already been matched so that+ -- wildcard generates code for the rest of the fields.+ compilePats' :: [QName] -> [PatField] -> Compile [JsStmt]+ compilePats' names (PFieldPun name:xs) =+ compilePats' names (PFieldPat (UnQual name) (PVar name):xs)++ compilePats' names (PFieldPat fieldname (PVar varName):xs) = do+ r <- compilePats' (fieldname : names) xs+ bindVar varName+ return $ JsVar (JsNameVar (UnQual varName))+ (JsGetProp (force exp) (JsNameVar fieldname))+ : r -- TODO: think about this force call++ compilePats' names (PFieldWildcard:xs) = do+ records <- liftM stateRecords get+ let fields = fromJust (lookup name records)+ fields' = fields \\ names+ f <- mapM (\fieldName -> do bindVar (unQual fieldName)+ return (JsVar (JsNameVar fieldName)+ (JsGetProp (force exp) (JsNameVar fieldName))))+ fields'+ r <- compilePats' names xs+ return $ f ++ r++ compilePats' _ [] = return []++ compilePats' _ (pat:_) = throwError (UnsupportedFieldPattern pat)++ unQual (Qual _ n) = n+ unQual (UnQual n) = n+ unQual Special{} = error "Trying to unqualify a Special..."++-- | Compile a literal value from a pattern match.+compilePLit :: JsExp -> Literal -> [JsStmt] -> Compile [JsStmt]+compilePLit exp literal body = do+ c <- ask+ lit <- readerCompileLit c literal+ return [JsIf (equalExps exp lit)+ body+ []]++ where -- Equality test for two expressions, with some optimizations.+ equalExps :: JsExp -> JsExp -> JsExp+ equalExps a b+ | isConstant a && isConstant b = JsEq a b+ | isConstant a = JsEq a (force b)+ | isConstant b = JsEq (force a) b+ | otherwise =+ JsApp (JsName (JsBuiltIn "equal")) [a,b]++-- | Compile as binding in pattern match+compilePAsPat :: JsExp -> Name -> Pat -> [JsStmt] -> Compile [JsStmt]+compilePAsPat exp name pat body = do+ bindVar name+ x <- compilePat exp pat body+ return ([JsVar (JsNameVar (UnQual name)) exp] ++ x)++-- | Compile a pattern application.+compilePApp :: QName -> [Pat] -> JsExp -> [JsStmt] -> Compile [JsStmt]+compilePApp cons pats exp body = do+ let forcedExp = force exp+ let boolIf b = return [JsIf (JsEq forcedExp (JsLit (JsBool b))) body []]+ case cons of+ -- Special-casing on the booleans.+ "True" -> boolIf True+ "False" -> boolIf False+ -- Everything else, generic:+ _ -> do+ rf <- fmap (lookup cons) (gets stateRecords)+ let recordFields =+ fromMaybe+ (error $ "Constructor '" ++ prettyPrint cons +++ "' was not found in stateRecords, did you try running this through GHC first?")+ rf+ substmts <- foldM (\body (field,pat) ->+ compilePat (JsGetProp forcedExp (JsNameVar field)) pat body)+ body+ (reverse (zip recordFields pats))+ qcons <- resolveName cons+ return [JsIf (forcedExp `JsInstanceOf` JsConstructor qcons)+ substmts+ []]++-- | Compile a pattern list.+compilePList :: [Pat] -> [JsStmt] -> JsExp -> Compile [JsStmt]+compilePList [] body exp =+ return [JsIf (JsEq (force exp) JsNull) body []]+compilePList pats body exp = do+ let forcedExp = force exp+ stmts <- foldM (\body (i,pat) -> compilePat (JsApp (JsName (JsBuiltIn "index"))+ [JsLit (JsInt i),forcedExp])+ pat+ body)+ body+ (reverse (zip [0..] pats))+ let patsLen = JsLit (JsInt (length pats))+ return [JsIf (JsApp (JsName (JsBuiltIn "listLen")) [forcedExp,patsLen])+ stmts+ []]++-- | Compile an infix pattern (e.g. cons and tuples.)+compileInfixPat :: JsExp -> Pat -> [JsStmt] -> Compile [JsStmt]+compileInfixPat exp pat@(PInfixApp left (Special cons) right) body =+ case cons of+ Cons -> do+ withScopedTmpJsName $ \tmpName -> do+ let forcedExp = JsName tmpName+ x = JsGetProp forcedExp (JsNameVar "car")+ xs = JsGetProp forcedExp (JsNameVar "cdr")+ rightMatch <- compilePat xs right body+ leftMatch <- compilePat x left rightMatch+ return [JsVar tmpName (force exp)+ ,JsIf (JsInstanceOf forcedExp (JsBuiltIn "Cons"))+ leftMatch+ []]+ _ -> throwError (UnsupportedPattern pat)+compileInfixPat _ pat _ = throwError (UnsupportedPattern pat)
+ src/Fay/Compiler/Print.hs view
@@ -0,0 +1,291 @@+{-# OPTIONS -fno-warn-orphans #-}+{-# OPTIONS -fno-warn-unused-do-bind #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TypeSynonymInstances #-}++-- | Simple code (non-pretty) printing.+--+-- No clever printing is done here. If you want pretty printing, use a+-- JS pretty printer. The output should be passed directly to a JS+-- compressor, anyway.+--+-- Special constructors and symbols in Haskell are encoded to+-- JavaScript appropriately.++module Fay.Compiler.Print where++import Fay.Types++import Control.Monad+import Control.Monad.State+import Data.Aeson.Encode+import qualified Data.ByteString.Lazy.UTF8 as UTF8+import Data.Default+import Data.List+import Data.String+import Language.Haskell.Exts.Syntax+import Prelude hiding (exp)++--------------------------------------------------------------------------------+-- Printing++-- | Print the JS to a flat string.+printJSString :: Printable a => a -> String+printJSString x = concat $ reverse $ psOutput $ execState (runPrinter (printJS x)) def++-- | Print the JS to a pretty string.+printJSPretty :: Printable a => a -> String+printJSPretty x = concat $ reverse $ psOutput $ execState (runPrinter (printJS x)) def { psPretty = True }++-- | Print literals. These need some special encoding for+-- JS-format literals. Could use the Text.JSON library.+instance Printable JsLit where+ printJS typ = write $+ let u8 = UTF8.toString . encode . UTF8.fromString+ in case typ of+ (JsChar char) -> u8 [char]+ (JsStr str) -> u8 str+ (JsInt int) -> show int+ (JsFloating rat) -> show rat+ (JsBool b) -> if b then "true" else "false"++-- | Print (and properly encode to JS) a qualified name.+instance Printable QName where+ printJS qname =+ case qname of+ Qual moduleName name -> moduleName +> "$" +> name+ UnQual name -> printJS name+ Special con -> printJS con++-- | Print module name.+instance Printable ModuleName where+ printJS (ModuleName "Fay$") =+ write "Fay$"+ printJS (ModuleName moduleName) = write $ go moduleName++ where go ('.':xs) = '$' : go xs+ go (x:xs) = normalizeName [x] ++ go xs+ go [] = []++-- | Print special constructors (tuples, list, etc.)+instance Printable SpecialCon where+ printJS specialCon =+ printJS $ (Qual (ModuleName "Fay$") . Ident) $+ case specialCon of+ UnitCon -> "unit"+ Cons -> "cons"+ _ -> error $ "Special constructor not supported: " ++ show specialCon++-- | Print (and properly encode) a name.+instance Printable Name where+ printJS name = write $+ case name of+ Ident ident -> encodeName ident+ Symbol sym -> encodeName sym++-- | Print a list of statements.+instance Printable [JsStmt] where+ printJS = mapM_ printJS++-- | Print a single statement.+instance Printable JsStmt where+ printJS (JsBlock stmts) =+ "{ " +> stmts +> "}"+ printJS (JsVar name expr) =+ "var " +> name +> " = " +> expr +> ";" +> newline+ printJS (JsUpdate name expr) =+ name +> " = " +> expr +> ";" +> newline+ printJS (JsSetProp name prop expr) =+ name +> "." +> prop +> " = " +> expr +> ";" +> newline+ printJS (JsSetPropExtern name prop expr) =+ name +> "['" +> prop +> "'] = " +> expr +> ";" +> newline+ printJS (JsIf exp thens elses) =+ "if (" +> exp +> ") {" +> newline +>+ indented (printJS thens) +>+ "}" +>+ (when (length elses > 0) $ " else {" +>+ indented (printJS elses) +>+ "}") +> newline+ printJS (JsEarlyReturn exp) =+ "return " +> exp +> ";" +> newline+ printJS (JsThrow exp) = do+ "throw " +> exp +> ";" +> newline+ printJS (JsWhile cond stmts) =+ "while (" +> cond +> ") {" +> newline +>+ indented (printJS stmts) +>+ "}" +> newline+ printJS JsContinue =+ printJS "continue;" +> newline+ printJS (JsMappedVar _ name expr) =+ "var " +> name +> " = " +> expr +> ";" +> newline++-- | Print an expression.+instance Printable JsExp where+ printJS (JsSeq es) = "(" +> intercalateM "," (map printJS es) +> ")"+ printJS (JsRawExp e) = write e+ printJS (JsName name) = printJS name+ printJS (JsThrowExp exp) =+ "(function(){ throw (" +> exp +> "); })()"+ printJS JsNull =+ printJS "null"+ printJS JsUndefined =+ printJS "undefined"+ printJS (JsLit lit) =+ printJS lit+ printJS (JsParen exp) =+ "(" +> exp +> ")"+ printJS (JsList exps) =+ "[" +> intercalateM "," (map printJS exps) +> printJS "]"+ printJS (JsNew name args) =+ "new " +> (JsApp (JsName name) args)+ printJS (JsIndex i exp) =+ "(" +> exp +> ")[" +> show i +> "]"+ printJS (JsEq exp1 exp2) =+ exp1 +> " === " +> exp2+ printJS (JsNeq exp1 exp2) =+ exp1 +> " !== " +> exp2+ printJS (JsGetProp exp prop) = exp +> "." +> prop+ printJS (JsLookup exp1 exp2) =+ exp1 +> "[" +> exp2 +> "]"+ printJS (JsUpdateProp name prop expr) =+ "(" +> name +> "." +> prop +> " = " +> expr +> ")"+ printJS (JsInfix op x y) =+ x +> " " +> op +> " " +> y+ printJS (JsGetPropExtern exp prop) =+ exp +> "[" +> (JsLit . JsStr) prop +> "]"+ printJS (JsUpdatePropExtern name prop expr) =+ "(" +> name +> "['" +> prop +> "'] = " +> expr +> ")"+ printJS (JsTernaryIf cond conseq alt) =+ cond +> " ? " +> conseq +> " : " +> alt+ printJS (JsInstanceOf exp classname) =+ exp +> " instanceof " +> classname+ printJS (JsObj assoc) =+ "{" +> (intercalateM "," (map cons assoc)) +> "}"+ where cons (key,value) = "\"" +> key +> "\": " +> value+ printJS (JsFun params stmts ret) =+ "function("+ +> (intercalateM "," (map printJS params))+ +> "){" +> newline+ +> indented (stmts +>+ case ret of+ Just ret' -> "return " +> ret' +> ";" +> newline+ Nothing -> return ())+ +> "}"+ printJS (JsApp op args) =+ (if isFunc op then JsParen op else op)+ +> "("+ +> (intercalateM "," (map printJS args))+ +> ")"+ where isFunc JsFun{..} = True; isFunc _ = False+ printJS (JsNegApp args) =+ "(-(" +> printJS args +> "))"++-- | Print one of the kinds of names.+instance Printable JsName where+ printJS name =+ case name of+ JsNameVar qname -> printJS qname+ JsThis -> write "this"+ JsThunk -> write "Fay$$$"+ JsForce -> write "Fay$$_"+ JsApply -> write "Fay$$__"+ JsParam i -> write ("$p" ++ show i)+ JsTmp i -> write ("$tmp" ++ show i)+ JsConstructor qname -> "$_" +> printJS qname+ JsBuiltIn qname -> "Fay$$" +> printJS qname+ JsParametrizedType -> write "type"++-- | Just write out strings.+instance Printable String where+ printJS = write++-- | A printer is a printable.+instance Printable (Printer ()) where+ printJS = id++--------------------------------------------------------------------------------+-- Name encoding++-- | Words reserved in haskell as well are not needed here:+-- case, class, do, else, if, import, in, let+reservedWords :: [String]+reservedWords = [+ "break", "catch", "const", "continue", "debugger", "delete", "enum", "export",+ "extends", "finally", "for", "function", "global", "implements", "instanceof",+ "interface", "new", "null", "package", "private", "protected", "public", "return",+ "static", "super", "switch", "this", "throw", "try", "typeof", "undefined",+ "var", "void", "while", "window", "with", "yield","true","false"]++-- | Encode a Haskell name to JavaScript.+encodeName :: String -> String+-- | This is a hack for names generated in the Haskell AST. Should be+-- removed once it's no longer needed.+encodeName ('$':'g':'e':'n':name) = "$gen_" ++ normalizeName name+encodeName name+ | name `elem` reservedWords = "$_" ++ normalizeName name+ | otherwise = normalizeName name++-- | Normalize the given name to JavaScript-valid names.+normalizeName :: [Char] -> [Char]+normalizeName name =+ concatMap encodeChar name++ where+ encodeChar c | c `elem` allowed = [c]+ | otherwise = escapeChar c+ allowed = ['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9'] ++ "_"+ escapeChar c = "$" ++ charId c ++ "$"+ charId c = show (fromEnum c)++--------------------------------------------------------------------------------+-- Printing+++-- | Print the given printer indented.+indented :: Printer a -> Printer ()+indented p = do+ PrintState{..} <- get+ if psPretty+ then do modify $ \s -> s { psIndentLevel = psIndentLevel + 1 }+ p+ modify $ \s -> s { psIndentLevel = psIndentLevel }+ else p >> return ()++-- | Output a newline.+newline :: Printer ()+newline = do+ PrintState{..} <- get+ when psPretty $ do+ write "\n"+ modify $ \s -> s { psNewline = True }++-- | Write out a string, updating the current position information.+write :: String -> Printer ()+write x = do+ PrintState{..} <- get+ let out = if psNewline then replicate (2*psIndentLevel) ' ' ++ x else x+ modify $ \s -> s { psOutput = out : psOutput+ , psLine = psLine + additionalLines+ , psColumn = if additionalLines > 0+ then length (concat (take 1 (reverse srclines)))+ else psColumn + length x+ , psNewline = False+ }+ return (error "Nothing to return for writer string.")++ where srclines = lines x+ additionalLines = length (filter (=='\n') x)++-- | Intercalate monadic action.+intercalateM :: String -> [Printer a] -> Printer ()+intercalateM _ [] = return ()+intercalateM _ [x] = x >> return ()+intercalateM str (x:xs) = do+ x+ write str+ intercalateM str xs++-- | Concatenate two printables.+(+>) :: (Printable a, Printable b) => a -> b -> Printer ()+pa +> pb = printJS pa >> printJS pb
+ src/Fay/Compiler/Typecheck.hs view
@@ -0,0 +1,42 @@+-- | Type-check using GHC.++module Fay.Compiler.Typecheck where++import Control.Monad.IO+import Data.List+import Data.Maybe+import Fay.Compiler.Misc+import Fay.Types+import qualified GHC.Paths as GHCPaths+import System.Process.Extra++-- | Call out to GHC to type-check the file.+typecheck :: Maybe FilePath -> Bool -> String -> Compile ()+typecheck packageConf wall fp = do+ cfg <- config id+ faydir <- io faySourceDir+ let includes = configDirectoryIncludes cfg++ -- Remove the fay source dir from includeDirs to prevent errors on FFI instance declarations.+ let includeDirs = map snd . filter ((/= faydir) . snd) . filter (isNothing . fst) $ includes+ let packages = nub . map (fromJust . fst) . filter (isJust . fst) $ includes++ ghcPackageDbArgs <-+ case packageConf of+ Nothing -> return []+ Just pk -> do+ flag <- io getGhcPackageDbFlag+ return [flag ++ '=' : pk]+ let flags =+ [ "-fno-code"+ , "-hide-package base"+ , "-cpp", "-DFAY=1"+ , "-main-is"+ , "Language.Fay.DummyMain"+ , "-i" ++ concat (intersperse ":" includeDirs)+ , fp ] ++ ghcPackageDbArgs ++ wallF ++ map ("-package " ++) packages+ res <- io $ readAllFromProcess GHCPaths.ghc flags ""+ either error (warn . fst) res+ where+ wallF | wall = ["-Wall"]+ | otherwise = []
+ src/Fay/Convert.hs view
@@ -0,0 +1,198 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TupleSections #-}+{-# OPTIONS -fno-warn-type-defaults #-}++-- | Convert a Haskell value to a (JSON representation of a) Fay value.++module Fay.Convert+ (showToFay+ ,readFromFay)+ where++import Control.Applicative+import Control.Monad+import Control.Monad.State+import Data.Aeson+import Data.Attoparsec.Number+import Data.Char+import Data.Data+import Data.Function+import Data.Generics.Aliases+import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as Map+import Data.Maybe+import Data.Text (Text)+import qualified Data.Text as Text+import qualified Data.Vector as Vector+import Numeric+import Safe+import qualified Text.Show.Pretty as Show++--------------------------------------------------------------------------------+-- The conversion functions.++-- | Convert a Haskell value to a value representing a Fay value.+showToFay :: Show a => a -> Maybe Value+showToFay = Show.reify >=> convert where+ convert value = case value of+ -- Special cases+ Show.Con "True" _ -> return (Bool True)+ Show.Con "False" _ -> return (Bool False)++ -- Objects/records+ Show.Con name values -> fmap (Object . Map.fromList . (("instance",string name) :))+ (slots values)+ Show.Rec name fields -> fmap (Object . Map.fromList . (("instance",string name) :))+ (mapM (uncurry keyval) fields)++ -- List types+ Show.Tuple values -> fmap (Array . Vector.fromList) (mapM convert values)+ Show.List values -> fmap (Array . Vector.fromList) (mapM convert values)++ -- Text types+ Show.String chars -> fmap string (readMay chars)+ Show.Char char -> fmap (string.return) (readMay char)++ -- Numeric types (everything treated as a double)+ Show.Neg{} -> double <|> int+ Show.Integer{} -> int+ Show.Float{} -> double+ Show.Ratio{} -> double+ where double = convertDouble value+ int = convertInt value++ -- Number converters+ convertDouble = fmap (Number . D) . pDouble+ convertInt = fmap (Number . I) . pInt++ -- Number parsers+ pDouble :: Show.Value -> Maybe Double+ pDouble value = case value of+ Show.Float str -> getDouble str+ Show.Ratio x y -> liftM2 (on (/) fromIntegral) (pInt x) (pInt y)+ Show.Neg str -> fmap (* (-1)) (pDouble str)+ _ -> Nothing+ pInt value = case value of+ Show.Integer str -> getInt str+ Show.Neg str -> fmap (* (-1)) (pInt str)+ _ -> Nothing++ -- Number readers+ getDouble :: String -> Maybe Double+ getDouble = fmap fst . listToMaybe . readFloat+ getInt :: String -> Maybe Integer+ getInt = fmap fst . listToMaybe . readInt 10 isDigit charToInt+ where charToInt c = fromEnum c - fromEnum '0'++ -- Utilities+ string = String . Text.pack+ slots = zipWithM keyval (map (("slot"++).show) [1::Int ..])+ keyval key val = fmap (Text.pack key,) (convert val)++-- | Convert a value representing a Fay value to a Haskell value.++readFromFay :: Data a => Value -> Maybe a+readFromFay value = do+ parseData value+ `ext1R` parseArray value+ `extR` parseDouble value+ `extR` parseInt value+ `extR` parseBool value+ `extR` parseString value+ `extR` parseText value++-- | Parse a data type or record.+parseData :: Data a => Value -> Maybe a+parseData value = result where+ result = getObject value >>= parseObject typ+ typ = dataTypeOf (fromJust result)+ getObject x =+ case x of+ Object obj -> return obj+ _ -> mzero++-- | Parse a data constructor from an object.+parseObject :: Data a => DataType -> HashMap Text Value -> Maybe a+parseObject typ obj = listToMaybe (catMaybes choices) where+ choices = map makeConstructor constructors+ constructors = dataTypeConstrs typ+ makeConstructor cons = do+ name <- Map.lookup (Text.pack "instance") obj >>= parseString+ guard (showConstr cons == name)+ if null fields+ then makeSimple obj cons+ else makeRecord obj cons fields++ where fields = constrFields cons++-- | Make a simple ADT constructor from an object: { "slot1": 1, "slot2": 2} -> Foo 1 2+makeSimple :: Data a => HashMap Text Value -> Constr -> Maybe a+makeSimple obj cons =+ evalStateT (fromConstrM (do i:next <- get+ put next+ value <- lift (Map.lookup (Text.pack ("slot" ++ show i)) obj)+ lift (readFromFay value))+ cons)+ [1..]++-- | Make a record from a key-value: { "x": 1 } -> Foo { x = 1 }+makeRecord :: Data a => HashMap Text Value -> Constr -> [String] -> Maybe a+makeRecord obj cons fields =+ evalStateT (fromConstrM (do key:next <- get+ put next+ value <- lift (Map.lookup (Text.pack key) obj)+ lift (readFromFay value))+ cons)+ fields++-- | Parse a double.+parseDouble :: Value -> Maybe Double+parseDouble value = do+ number <- parseNumber value+ case number of+ I n -> return (fromIntegral n)+ D n -> return n++-- | Parse an int.+parseInt :: Value -> Maybe Int+parseInt value = do+ number <- parseNumber value+ case number of+ I n -> return (fromIntegral n)+ _ -> mzero++-- | Parse a number.+parseNumber :: Value -> Maybe Number+parseNumber value =+ case value of+ Number n -> return n+ _ -> mzero++-- | Parse a bool.+parseBool :: Value -> Maybe Bool+parseBool value =+ case value of+ Bool n -> return n+ _ -> mzero++-- | Parse a string.+parseString :: Value -> Maybe String+parseString value =+ case value of+ String s -> return (Text.unpack s)+ _ -> mzero++-- | Parse a Text.+parseText :: Value -> Maybe Text+parseText value =+ case value of+ String s -> return s+ _ -> mzero++-- | Parse an array.+parseArray :: Data a => Value -> Maybe [a]+parseArray value =+ case value of+ Array xs -> mapM readFromFay (Vector.toList xs)+ _ -> mzero
+ src/Fay/Types.hs view
@@ -0,0 +1,339 @@+{-# OPTIONS -fno-warn-orphans #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}++-- | All Fay types and instances.++module Fay.Types+ (JsStmt(..)+ ,JsExp(..)+ ,JsLit(..)+ ,JsName(..)+ ,CompileError(..)+ ,Compile(..)+ ,CompilesTo(..)+ ,Printable(..)+ ,Fay+ ,CompileReader(..)+ ,CompileWriter(..)+ ,CompileConfig(..)+ ,CompileState(..)+ ,addCurrentExport+ ,getCurrentExports+ ,getExportsFor+ ,faySourceDir+ ,FundamentalType(..)+ ,PrintState(..)+ ,Printer(..)+ ,Mapping(..)+ ,SerializeContext(..))+ where++import Control.Applicative+import Control.Monad.Error (Error, ErrorT, MonadError)+import Control.Monad.Identity (Identity)+import Control.Monad.State+import Control.Monad.RWS+import Data.Default+import Data.Maybe+import Data.Map (Map)+import qualified Data.Map as M+import Data.Set (Set)+import qualified Data.Set as S+import Data.String+import Language.Haskell.Exts+import System.FilePath++import Fay.Compiler.ModuleScope (ModuleScope)+import Paths_fay++--------------------------------------------------------------------------------+-- Compiler types++-- | Configuration of the compiler.+data CompileConfig = CompileConfig+ { configOptimize :: Bool -- ^ Run optimizations+ , configFlattenApps :: Bool -- ^ Flatten function application?+ , configExportBuiltins :: Bool -- ^ Export built-in functions?+ , configExportRuntime :: Bool -- ^ Export the runtime?+ , configExportStdlib :: Bool -- ^ Export the stdlib?+ , configExportStdlibOnly :: Bool -- ^ Export /only/ the stdlib?+ , configDispatchers :: Bool -- ^ Export dispatchers?+ , configDispatcherOnly :: Bool -- ^ Export /only/ the dispatcher?+ , configNaked :: Bool -- ^ Export without a module wrapper?+ , configDirectoryIncludes :: [(Maybe String, FilePath)] -- ^ Possibly a fay package name, and a include directory.+ , configPrettyPrint :: Bool -- ^ Pretty print the JS output?+ , configHtmlWrapper :: Bool -- ^ Output a HTML file including the produced JS.+ , configHtmlJSLibs :: [FilePath] -- ^ Any JS files to link to in the HTML.+ , configLibrary :: Bool -- ^ Don't invoke main in the produced JS.+ , configWarn :: Bool -- ^ Warn on dubious stuff, not related to typechecking.+ , configFilePath :: Maybe FilePath -- ^ File path to output to.+ -- TODO: This flag is not used thoroughly, decide if it's needed.+ , configTypecheck :: Bool -- ^ Typecheck with GHC.+ , configWall :: Bool -- ^ Typecheck with -Wall.+ , configGClosure :: Bool -- ^ Run Google Closure on the produced JS.+ , configPackageConf :: Maybe FilePath -- ^ The package config e.g. packages-6.12.3.+ , configPackages :: [String] -- ^ Included Fay packages.+ } deriving (Show)++-- | State of the compiler.+data CompileState = CompileState+ { _stateExports :: Map ModuleName (Set QName) -- ^ Collects exports from modules+ , stateFilePath :: FilePath -- ^ Current file path. TODO: Used?+ , stateRecordTypes :: [(QName,[QName])] -- ^ Map types to constructors+ , stateRecords :: [(QName,[QName])] -- ^ Map constructors to fields+ , stateImported :: [(ModuleName,FilePath)] -- ^ Map of all imported modules and their source locations.+ , stateNameDepth :: Integer -- ^ Depth of the current lexical scope.+ , stateLocalScope :: Set Name -- ^ Names in the current lexical scope.+ , stateModuleScope :: ModuleScope -- ^ Names in the module scope.+ , stateModuleName :: ModuleName -- ^ Name of the module currently being compiled.+ } deriving (Show)++-- | Things written out by the compiler.+data CompileWriter = CompileWriter+ { writerCons :: [JsStmt] -- ^ Constructors.+ , writerFayToJs :: [JsStmt] -- ^ Fay to JS dispatchers.+ , writerJsToFay :: [JsStmt] -- ^ JS to Fay dispatchers.+ }+ deriving (Show)++-- | Simple concatenating instance.+instance Monoid CompileWriter where+ mempty = CompileWriter [] [] []+ mappend (CompileWriter a b c) (CompileWriter x y z) =+ CompileWriter (a++x) (b++y) (c++z)++-- | Configuration and globals for the compiler.+data CompileReader = CompileReader+ { readerConfig :: CompileConfig -- ^ The compilation configuration.+ , readerCompileLit :: Literal -> Compile JsExp+ , readerCompileDecls :: Bool -> [Decl] -> Compile [JsStmt]+ }++-- | The data-files source directory.+faySourceDir :: IO FilePath+faySourceDir = fmap (takeDirectory . takeDirectory . takeDirectory) (getDataFileName "src/Language/Fay/Stdlib.hs")++-- | Adds a new export to '_stateExports' for the module specified by+-- 'stateModuleName'.+addCurrentExport :: QName -> CompileState -> CompileState+addCurrentExport q cs =+ cs { _stateExports = M.insert (stateModuleName cs) qnames $ _stateExports cs}+ where+ qnames = maybe (S.singleton q) (S.insert q)+ $ M.lookup (stateModuleName cs) (_stateExports cs)++-- | Get all of the exported identifiers for the current module.+getCurrentExports :: CompileState -> Set QName+getCurrentExports cs = getExportsFor (stateModuleName cs) cs++-- | Get all of the exported identifiers for the given module.+getExportsFor :: ModuleName -> CompileState -> Set QName+getExportsFor mn cs = fromMaybe S.empty $ M.lookup mn (_stateExports cs)++-- | Compile monad.+newtype Compile a = Compile+ { unCompile :: RWST CompileReader CompileWriter CompileState (ErrorT CompileError IO) a -- ^ Run the compiler.+ }+ deriving (MonadState CompileState+ ,MonadError CompileError+ ,MonadReader CompileReader+ ,MonadWriter CompileWriter+ ,MonadIO+ ,Monad+ ,Functor+ ,Applicative)++-- | Just a convenience class to generalize the parsing/printing of+-- various types of syntax.+class (Parseable from,Printable to) => CompilesTo from to | from -> to where+ compileTo :: from -> Compile to++-- | A source mapping.+data Mapping = Mapping+ { mappingName :: String -- ^ The name of the mapping.+ , mappingFrom :: SrcLoc -- ^ The original source location.+ , mappingTo :: SrcLoc -- ^ The new source location.+ } deriving (Show)++-- | The state of the pretty printer.+data PrintState = PrintState+ { psPretty :: Bool -- ^ Are we to pretty print?+ , psLine :: Int -- ^ The current line.+ , psColumn :: Int -- ^ Current column.+ , psMapping :: [Mapping] -- ^ Source mappings.+ , psIndentLevel :: Int -- ^ Current indentation level.+ , psOutput :: [String] -- ^ The current output. TODO: Make more efficient.+ , psNewline :: Bool -- ^ Just outputted a newline?+ }++-- | Default state.+instance Default PrintState where+ def = PrintState False 0 0 [] 0 [] False++-- | The printer monad.+newtype Printer a = Printer { runPrinter :: State PrintState a }+ deriving (Monad,Functor,MonadState PrintState)++-- | Print some value.+class Printable a where+ printJS :: a -> Printer ()++-- | Error type.+data CompileError+ = ParseError SrcLoc String+ | UnsupportedDeclaration Decl+ | UnsupportedExportSpec ExportSpec+ | UnsupportedMatchSyntax Match+ | UnsupportedWhereInMatch Match+ | UnsupportedExpression Exp+ | UnsupportedLiteral Literal+ | UnsupportedLetBinding Decl+ | UnsupportedOperator QOp+ | UnsupportedPattern Pat+ | UnsupportedFieldPattern PatField+ | UnsupportedRhs Rhs+ | UnsupportedGuardedAlts GuardedAlts+ | UnsupportedWhereInAlt Alt+ | UnsupportedImport ImportDecl+ | UnsupportedQualStmt QualStmt+ | EmptyDoBlock+ | UnsupportedModuleSyntax Module+ | LetUnsupported+ | InvalidDoBlock+ | RecursiveDoUnsupported+ | Couldn'tFindImport ModuleName [FilePath]+ | FfiNeedsTypeSig Decl+ | FfiFormatBadChars String+ | FfiFormatNoSuchArg Int+ | FfiFormatIncompleteArg+ | FfiFormatInvalidJavaScript SrcLoc String String+ | UnableResolveUnqualified Name+ | UnableResolveQualified QName+ deriving (Show)+instance Error CompileError++-- | The JavaScript FFI interfacing monad.+newtype Fay a = Fay (Identity a)+ deriving Monad++--------------------------------------------------------------------------------+-- JS AST types++-- | Statement type.+data JsStmt+ = JsVar JsName JsExp+ | JsMappedVar SrcLoc JsName JsExp+ | JsIf JsExp [JsStmt] [JsStmt]+ | JsEarlyReturn JsExp+ | JsThrow JsExp+ | JsWhile JsExp [JsStmt]+ | JsUpdate JsName JsExp+ | JsSetProp JsName JsName JsExp+ | JsSetPropExtern JsName JsName JsExp+ | JsContinue+ | JsBlock [JsStmt]+ deriving (Show,Eq)++-- | Expression type.+data JsExp+ = JsName JsName+ | JsRawExp String+ | JsSeq [JsExp]+ | JsFun [JsName] [JsStmt] (Maybe JsExp)+ | JsLit JsLit+ | JsApp JsExp [JsExp]+ | JsNegApp JsExp+ | JsTernaryIf JsExp JsExp JsExp+ | JsNull+ | JsParen JsExp+ | JsGetProp JsExp JsName+ | JsLookup JsExp JsExp+ | JsUpdateProp JsExp JsName JsExp+ | JsGetPropExtern JsExp String+ | JsUpdatePropExtern JsExp JsName JsExp+ | JsList [JsExp]+ | JsNew JsName [JsExp]+ | JsThrowExp JsExp+ | JsInstanceOf JsExp JsName+ | JsIndex Int JsExp+ | JsEq JsExp JsExp+ | JsNeq JsExp JsExp+ | JsInfix String JsExp JsExp -- Used to optimize *, /, +, etc+ | JsObj [(String,JsExp)]+ | JsUndefined+ deriving (Show,Eq)++-- | A name of some kind.+data JsName+ = JsNameVar QName+ | JsThis+ | JsParametrizedType+ | JsThunk+ | JsForce+ | JsApply+ | JsParam Integer+ | JsTmp Integer+ | JsConstructor QName+ | JsBuiltIn Name+ deriving (Eq,Show)++-- | Literal value type.+data JsLit+ = JsChar Char+ | JsStr String+ | JsInt Int+ | JsFloating Double+ | JsBool Bool+ deriving (Show,Eq)++-- | Just handy to have.+instance IsString JsLit where fromString = JsStr++-- | These are the data types that are serializable directly to native+-- JS data types. Strings, floating points and arrays. The others are:+-- actions in the JS monad, which are thunks that shouldn't be forced+-- when serialized but wrapped up as JS zero-arg functions, and+-- unknown types can't be converted but should at least be forced.+data FundamentalType+ -- Recursive types.+ = FunctionType [FundamentalType]+ | JsType FundamentalType+ | ListType FundamentalType+ | TupleType [FundamentalType]+ | UserDefined Name [FundamentalType]+ | Defined FundamentalType+ | Nullable FundamentalType+ -- Simple types.+ | DateType+ | StringType+ | DoubleType+ | IntType+ | BoolType+ | PtrType+ -- Automatically serialize this type.+ | Automatic+ -- Unknown.+ | UnknownType+ deriving (Show)++-- | Helpful for some things.+instance IsString Name where+ fromString = Ident++-- | Helpful for some things.+instance IsString QName where+ fromString = UnQual . Ident++-- | Helpful for writing qualified symbols (Fay.*).+instance IsString ModuleName where+ fromString = ModuleName++-- | The serialization context indicates whether we're currently+-- serializing some value or a particular field in a user-defined data+-- type.+data SerializeContext = SerializeAnywhere | SerializeUserArg Int+ deriving (Read,Show,Eq)
− src/Language/Fay.hs
@@ -1,175 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE ViewPatterns #-}--module Language.Fay- (module Language.Fay.Types- ,compileFile- ,compileFileWithState- ,compileFromTo- ,compileFromToAndGenerateHtml- ,toJsName- ,showCompileError)- where--import Language.Fay.Compiler (compileToplevelModule,- compileViaStr)-import Language.Fay.Compiler.Misc (printSrcLoc)-import Language.Fay.Compiler.Packages-import Language.Fay.Print-import Language.Fay.Types--import Control.Applicative-import Control.Monad-import Data.List-import Language.Haskell.Exts (prettyPrint)-import Language.Haskell.Exts.Syntax-import Paths_fay-import System.FilePath---- | Compile the given file and write the output to the given path, or--- if nothing given, stdout.-compileFromTo :: CompileConfig -> FilePath -> Maybe FilePath -> IO ()-compileFromTo config filein fileout = do- result <- maybe (compileFile config filein)- (compileFromToAndGenerateHtml config filein)- fileout- case result of- Right out -> maybe (putStrLn out) (flip writeFile out) fileout- Left err -> error $ showCompileError $ err---- | Compile the given file and write to the output, also generate any HTML.-compileFromToAndGenerateHtml :: CompileConfig -> FilePath -> FilePath -> IO (Either CompileError String)-compileFromToAndGenerateHtml config filein fileout = do- result <- compileFile config { configFilePath = Just filein } filein- case result of- Right out -> do- when (configHtmlWrapper config) $- writeFile (replaceExtension fileout "html") $ unlines [- "<!doctype html>"- , "<html>"- , " <head>"- ," <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>"- , unlines . map (" "++) . map makeScriptTagSrc $ configHtmlJSLibs config- , " " ++ makeScriptTagSrc relativeJsPath- , " </script>"- , " </head>"- , " <body>"- , " </body>"- , "</html>"]- return (Right out)- where relativeJsPath = makeRelative (dropFileName fileout) fileout- makeScriptTagSrc :: FilePath -> String- makeScriptTagSrc = \s ->- "<script type=\"text/javascript\" src=\"" ++ s ++ "\"></script>"- Left err -> return (Left err)---- | Compile the given file.-compileFile :: CompileConfig -> FilePath -> IO (Either CompileError String)-compileFile config filein = do- either Left (Right . fst) <$> compileFileWithState config filein--compileFileWithState :: CompileConfig -> FilePath -> IO (Either CompileError (String,CompileState))-compileFileWithState config filein = do- runtime <- getDataFileName "js/runtime.js"- hscode <- readFile filein- raw <- readFile runtime- config' <- resolvePackages config- compileToModule filein config' raw compileToplevelModule hscode---- | Compile the given module to a runnable module.-compileToModule :: (Show from,Show to,CompilesTo from to)- => FilePath- -> CompileConfig -> String -> (from -> Compile to) -> String- -> IO (Either CompileError (String,CompileState))-compileToModule filepath config raw with hscode = do- result <- compileViaStr filepath config with hscode- case result of- Left err -> return (Left err)- Right (PrintState{..},state) ->- return $ Right $ (generate (concat (reverse psOutput))- (stateExports state)- (stateModuleName state), state)-- where generate jscode exports (ModuleName (clean -> modulename)) = unlines- ["/** @constructor"- ,"*/"- ,"var " ++ modulename ++ " = function(){"- ,raw- ,jscode- ,"// Exports"- ,unlines (map printExport exports)- ,"// Built-ins"- ,"this._ = _;"- ,if configExportBuiltins config- then unlines ["this.$ = $;"- ,"this.$fayToJs = Fay$$fayToJs;"- ,"this.$jsToFay = Fay$$jsToFay;"- ]- else ""- ,"};"- ,if not (configLibrary config)- then unlines [";"- ,"var main = new " ++ modulename ++ "();"- ,"main._(main." ++ modulename ++ "$main);"- ]- else ""- ]- clean ('.':cs) = '$' : clean cs- clean (c:cs) = c : clean cs- clean [] = []---- | Print an this.x = x; export out.-printExport :: QName -> String-printExport name =- printJSString (JsSetProp JsThis- (JsNameVar name)- (JsName (JsNameVar name)))---- | Convert a Haskell filename to a JS filename.-toJsName :: String -> String-toJsName x = case reverse x of- ('s':'h':'.': (reverse -> file)) -> file ++ ".js"- _ -> x---- | Print a compile error for human consumption.-showCompileError :: CompileError -> String-showCompileError e = case e of- ParseError _ err -> err- UnsupportedDeclaration d -> "unsupported declaration: " ++ prettyPrint d- UnsupportedExportSpec es -> "unsupported export specification: " ++ prettyPrint es- UnsupportedMatchSyntax m -> "unsupported match/binding syntax: " ++ prettyPrint m- UnsupportedWhereInMatch m -> "unsupported `where' syntax: " ++ prettyPrint m- UnsupportedWhereInAlt alt -> "`where' not supported here: " ++ prettyPrint alt- UnsupportedExpression expr -> "unsupported expression syntax: " ++ prettyPrint expr- UnsupportedQualStmt stmt -> "unsupported list qualifier: " ++ prettyPrint stmt- UnsupportedLiteral lit -> "unsupported literal syntax: " ++ prettyPrint lit- UnsupportedLetBinding d -> "unsupported let binding: " ++ prettyPrint d- UnsupportedOperator qop -> "unsupported operator syntax: " ++ prettyPrint qop- UnsupportedPattern pat -> "unsupported pattern syntax: " ++ prettyPrint pat- UnsupportedRhs rhs -> "unsupported right-hand side syntax: " ++ prettyPrint rhs- UnsupportedGuardedAlts ga -> "unsupported guarded alts: " ++ prettyPrint ga- EmptyDoBlock -> "empty `do' block"- UnsupportedModuleSyntax{} -> "unsupported module syntax (may be supported later)"- LetUnsupported -> "let not supported here"- InvalidDoBlock -> "invalid `do' block"- RecursiveDoUnsupported -> "recursive `do' isn't supported"- FfiNeedsTypeSig d -> "your FFI declaration needs a type signature: " ++ prettyPrint d- FfiFormatBadChars cs -> "invalid characters for FFI format string: " ++ show cs- FfiFormatNoSuchArg i -> "no such argument in FFI format string: " ++ show i- FfiFormatIncompleteArg -> "incomplete `%' syntax in FFI format string"- FfiFormatInvalidJavaScript srcloc code err ->- printSrcLoc srcloc ++ ":" ++- "\ninvalid JavaScript code in FFI format string:\n"- ++ err ++ "\nin " ++ code- UnsupportedFieldPattern p -> "unsupported field pattern: " ++ prettyPrint p- UnsupportedImport i -> "unsupported import syntax, we're too lazy: " ++ prettyPrint i- Couldn'tFindImport i places ->- "could not find an import in the path: " ++ prettyPrint i ++ ", \n" ++- "searched in these places: " ++ intercalate ", " places- UnableResolveUnqualified name -> "unable to resolve unqualified name " ++ prettyPrint name- UnableResolveQualified qname -> "unable to resolve qualified names " ++ prettyPrint qname- UnableResolveCachedImport name -> "unable to resolve cached import " ++ prettyPrint name
− src/Language/Fay/Compiler.hs
@@ -1,1162 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE ViewPatterns #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# OPTIONS -Wall -fno-warn-name-shadowing -fno-warn-orphans #-}---- | The Haskell→Javascript compiler.--module Language.Fay.Compiler- (runCompile- ,compileViaStr- ,compileForDocs- ,compileToAst- ,compileModule- ,compileExp- ,compileDecl- ,printCompile- ,printTestCompile- ,compileToplevelModule)- where--import Language.Fay.Compiler.FFI-import Language.Fay.Compiler.Misc-import Language.Fay.Compiler.Optimizer-import Language.Fay.ModuleScope (bindAsLocals, findTopLevelNames, moduleLocals)-import Language.Fay.Print (printJSString)-import qualified Language.Fay.Stdlib as Stdlib-import Language.Fay.Types--import Control.Applicative-import Control.Monad.Error-import Control.Monad.IO-import Control.Monad.State-import Control.Monad.RWS-import Data.Default (def)-import Data.List-import Data.List.Extra-import qualified Data.Map as M-import qualified Data.Set as S-import Data.Maybe-import qualified GHC.Paths as GHCPaths-import Language.Haskell.Exts-import System.Directory (doesFileExist)-import System.FilePath ((</>))-import System.Process.Extra------------------------------------------------------------------------------------- Top level entry points---- | Run the compiler.-runCompile :: CompileReader -> CompileState- -> Compile a- -> IO (Either CompileError (a,CompileState))-runCompile reader state m =- fmap (fmap dropWriter)- (runErrorT (runRWST (unCompile m) reader state))-- where dropWriter (a,s,_w) = (a,s)---- | Compile a Haskell source string to a JavaScript source string.-compileViaStr :: (Show from,Show to,CompilesTo from to)- => FilePath- -> CompileConfig- -> (from -> Compile to)- -> String- -> IO (Either CompileError (PrintState,CompileState))-compileViaStr filepath config with from = do- cs <- defaultCompileState- rs <- defaultCompileReader config- runCompile rs- (cs { stateFilePath = filepath })- (parseResult (throwError . uncurry ParseError)- (fmap (\x -> execState (runPrinter (printJS x)) printConfig) . with)- (parseFay filepath from))-- where printConfig = def { psPretty = configPrettyPrint config }---- | Compile a Haskell source string to a JavaScript source string.-compileToAst :: (Show from,Show to,CompilesTo from to)- => FilePath- -> CompileReader- -> CompileState- -> (from -> Compile to)- -> String- -> IO (Either CompileError (to,CompileState))-compileToAst filepath reader state with from =- runCompile reader- state- (parseResult (throwError . uncurry ParseError)- with- (parseFay filepath from))---- | Parse some Fay code.-parseFay :: Parseable ast => FilePath -> String -> ParseResult ast-parseFay filepath = parseWithMode parseMode { parseFilename = filepath } . applyCPP---- | Apply incredibly simplistic CPP handling. It only recognizes the following:------ > #if FAY--- > #ifdef FAY--- > #ifndef FAY--- > #else--- > #endif------ Note that this implementation replaces all removed lines with blanks, so--- that line numbers remain accurate.-applyCPP :: String -> String-applyCPP =- unlines . loop NoCPP . lines- where- loop _ [] = []- loop state ("#if FAY":rest) = "" : loop (CPPIf True state) rest- loop state ("#ifdef FAY":rest) = "" : loop (CPPIf True state) rest- loop state ("#ifndef FAY":rest) = "" : loop (CPPIf False state) rest- loop (CPPIf b oldState) ("#else":rest) = "" : loop (CPPElse (not b) oldState) rest- loop (CPPIf _ oldState) ("#endif":rest) = "" : loop oldState rest- loop (CPPElse _ oldState) ("#endif":rest) = "" : loop oldState rest- loop state (x:rest) = (if toInclude state then x else "") : loop state rest-- toInclude NoCPP = True- toInclude (CPPIf x state) = x && toInclude state- toInclude (CPPElse x state) = x && toInclude state--data CPPState = NoCPP- | CPPIf Bool CPPState- | CPPElse Bool CPPState---- | The parse mode for Fay.-parseMode :: ParseMode-parseMode = defaultParseMode { extensions =- [GADTs,StandaloneDeriving,PackageImports,EmptyDataDecls,TypeOperators,RecordWildCards,NamedFieldPuns] }---- | Compile the given input and print the output out prettily.-printCompile :: (Show from,Show to,CompilesTo from to)- => CompileConfig- -> (from -> Compile to)- -> String- -> IO ()-printCompile config with from = do- result <- compileViaStr "<interactive>" config { configPrettyPrint = True } with from- case result of- Left err -> print err- Right (PrintState{..},_) -> do- putStrLn (concat (reverse (psOutput)))---- | Compile a String of Fay and print it as beautified JavaScript.-printTestCompile :: String -> IO ()-printTestCompile = printCompile def { configWarn = False } compileModule---- | Compile the given Fay code for the documentation. This is--- specialised because the documentation isn't really “real”--- compilation.-compileForDocs :: Module -> Compile [JsStmt]-compileForDocs mod = do- initialPass mod- compileModule mod---- | Compile the top-level Fay module.-compileToplevelModule :: Module -> Compile [JsStmt]-compileToplevelModule mod@(Module _ (ModuleName modulename) _ _ _ _ _) = do- cfg <- config id- -- Remove the fay source dir from the includes, -package fay is already supplied.- -- This will prevent errors on FFI instance declarations.- faydir <- io faySourceDir- let includeDirs = filter (/= faydir) (configDirectoryIncludes cfg)-- when (configTypecheck cfg) $- typecheck (configPackageConf cfg) includeDirs [] (configWall cfg) $- fromMaybe modulename $ configFilePath cfg- initialPass mod- cs <- io defaultCompileState- modify $ \s -> s { stateImported = stateImported cs }- stmts <- compileModule mod- fay2js <- do syms <- gets stateFayToJs- return $ if null syms then [] else [fayToJsDispatcher syms]- js2fay <- do syms <- gets stateJsToFay- return $ if null syms then [] else [jsToFayDispatcher syms]- let maybeOptimize = if configOptimize cfg then runOptimizer optimizeToplevel else id- return (maybeOptimize (stmts ++ fay2js ++ js2fay))------------------------------------------------------------------------------------- Initial pass-through collecting record definitions--initialPass :: Module -> Compile ()-initialPass (Module _ _ _ Nothing _ imports decls) = do- mapM_ initialPass_import imports- mapM_ initialPass_decl decls-initialPass mod = throwError (UnsupportedModuleSyntax mod)--initialPass_import :: ImportDecl -> Compile ()-initialPass_import (ImportDecl _ _ _ _ Just{} _ _) = do- return ()--- warn $ "import with package syntax ignored: " ++ prettyPrint i-initialPass_import (ImportDecl _ name False _ Nothing Nothing _) = do- void $ initialPass_unlessImported name $ \filepath contents -> do- state <- get- reader <- ask- result <- liftIO $ initialPass_records filepath reader state initialPass contents- case result of- Right ((),st) -> do- -- Merges the state gotten from passing through an imported- -- module with the current state. We can assume no duplicate- -- records exist since GHC would pick that up.- modify $ \s -> s { stateRecords = stateRecords st- , stateRecordTypes = stateRecordTypes st- , stateImported = stateImported st- }- Left err -> throwError err- return ()-initialPass_import i = throwError $ UnsupportedImport i---- | Don't re-import the same modules.-initialPass_unlessImported :: ModuleName- -> (FilePath -> String -> Compile ())- -> Compile ()-initialPass_unlessImported name importIt = do- imported <- gets stateImported- case lookup name imported of- Just _ -> return ()- Nothing -> do- dirs <- configDirectoryIncludes <$> config id- (filepath,contents) <- findImport dirs name- modify $ \s -> s { stateImported = (name,filepath) : imported }- importIt filepath contents--initialPass_records :: (Show from,Parseable from)- => FilePath- -> CompileReader- -> CompileState- -> (from -> Compile ())- -> String- -> IO (Either CompileError ((),CompileState))-initialPass_records filepath compileReader compileState with from =- runCompile compileReader- compileState- (parseResult (throwError . uncurry ParseError)- with- (parseFay filepath from))--initialPass_decl :: Decl -> Compile ()-initialPass_decl decl = do- case decl of- DataDecl _loc DataType _ctx name _tyvarb qualcondecls _deriv -> do- let ns = flip map qualcondecls (\(QualConDecl _loc' _tyvarbinds _ctx' condecl) -> conDeclName condecl)- addRecordTypeState name ns- _ -> return ()--- case decl of- DataDecl _ DataType _ _ _ constructors _ -> initialPass_dataDecl constructors- GDataDecl _ DataType _l _i _v _n decls _ -> initialPass_dataDecl (map convertGADT decls)- _ -> return ()-- where- addRecordTypeState name cons = modify $ \s -> s- { stateRecordTypes = (UnQual name, map UnQual cons) : stateRecordTypes s }-- conDeclName (ConDecl n _) = n- conDeclName (InfixConDecl _ n _) = n- conDeclName (RecDecl n _) = n----- | Collect record definitions and store record name and field names.--- A ConDecl will have fields named slot1..slotN-initialPass_dataDecl :: [QualConDecl] -> Compile ()-initialPass_dataDecl constructors = do- forM_ constructors $ \(QualConDecl _ _ _ condecl) ->- case condecl of- ConDecl name types -> do- let fields = map (Ident . ("slot"++) . show . fst) . zip [1 :: Integer ..] $ types- addRecordState name fields- InfixConDecl _t1 name _t2 ->- addRecordState name ["slot1", "slot2"]- RecDecl name fields' -> do- let fields = concatMap fst fields'- addRecordState name fields-- where- addRecordState :: Name -> [Name] -> Compile ()- addRecordState name fields = modify $ \s -> s- { stateRecords = (UnQual name,map UnQual fields) : stateRecords s }------------------------------------------------------------------------------------- Typechecking--typecheck :: Maybe FilePath -> [FilePath] -> [String] -> Bool -> String -> Compile ()-typecheck packageConf includeDirs ghcFlags wall fp = do- ghcPackageDbArgs <-- case packageConf of- Nothing -> return []- Just pk -> do- flag <- liftIO getGhcPackageDbFlag- return [flag ++ '=' : pk]- res <- liftIO $ readAllFromProcess GHCPaths.ghc (- ["-fno-code"- ,"-package fay"- ,"-main-is"- ,"Language.Fay.DummyMain"- ,fp]- ++ ghcPackageDbArgs- ++ map ("-i" ++) includeDirs ++ ghcFlags ++ wallF) ""- either error (warn . fst) res- where- wallF | wall = ["-Wall"]- | otherwise = []------------------------------------------------------------------------------------- Compilers---- | Compile Haskell module.-compileModule :: Module -> Compile [JsStmt]-compileModule (Module _ modulename _pragmas Nothing exports imports decls) =- withModuleScope $ do- modify $ \s -> s { stateModuleName = modulename- , stateExports = []- , stateModuleScope = findTopLevelNames modulename decls- }- imported <- fmap concat (mapM compileImport imports)- current <- compileDecls True decls-- case exports of- Just exps -> mapM_ emitExport exps- Nothing -> do- exps <- moduleLocals modulename <$> gets stateModuleScope- modify $ \s -> s { stateExports = exps ++ stateExports s }-- return (imported ++ current)-compileModule mod = throwError (UnsupportedModuleSyntax mod)--instance CompilesTo Module [JsStmt] where compileTo = compileModule--findImport :: [FilePath] -> ModuleName -> Compile (FilePath,String)-findImport alldirs mname = go alldirs mname where- go (dir:dirs) name = do- exists <- io (doesFileExist path)- if exists- then fmap (path,) (fmap stdlibHack (io (readFile path)))- else go dirs name- where- path = dir </> replace '.' '/' (prettyPrint name) ++ ".hs"- replace c r = map (\x -> if x == c then r else x)- go [] name =- throwError $ Couldn'tFindImport name alldirs-- stdlibHack- | mname == ModuleName "Language.Fay.Stdlib" = \s -> s ++ "\n\ndata Maybe a = Just a | Nothing"- | mname == ModuleName "Language.Fay.FFI" = const "module Language.Fay.FFI where\n\ndata Nullable a = Nullable a | Null\n\ndata Defined a = Defined a | Undefined"- | otherwise = id---- | Compile the given import.-compileImport :: ImportDecl -> Compile [JsStmt]-compileImport (ImportDecl _ _ _ _ Just{} _ _) = do--- warn $ "import with package syntax ignored: " ++ prettyPrint i- return []-compileImport (ImportDecl _ name False _ Nothing Nothing Nothing) =- compileImportWithFilter name (const $ return True)-compileImport (ImportDecl _ name False _ Nothing Nothing (Just (True, specs))) =- compileImportWithFilter name (fmap not . imported specs)-compileImport (ImportDecl _ name False _ Nothing Nothing (Just (False, specs))) =- compileImportWithFilter name (imported specs)-compileImport i =- throwError $ UnsupportedImport i--imported :: [ImportSpec] -> QName -> Compile Bool-imported is qn = anyM (matching qn) is- where- matching :: QName -> ImportSpec -> Compile Bool- matching (Qual _ _) (IAbs _) = return True -- Types are always OK- matching (Qual _ name) (IVar var) = return $ name == var- matching (Qual _ name) (IThingAll typ) = do- recs <- typeToRecs $ UnQual typ- if UnQual name `elem` recs- then return True- else do- fields <- typeToFields $ UnQual typ- return $ UnQual name `elem` fields- matching (Qual _ name) (IThingWith typ cns) =- flip anyM cns $ \cn -> case cn of- ConName _ -> do- recs <- typeToRecs $ UnQual typ- return $ UnQual name `elem` recs- VarName _ -> do- fields <- typeToFields $ UnQual typ- return $ UnQual name `elem` fields- matching q is = error $ "compileImport: Unsupported QName ImportSpec combination " ++ show (q, is) ++ ", this is a bug!"---compileImportWithFilter :: ModuleName -> (QName -> Compile Bool) -> Compile [JsStmt]-compileImportWithFilter name importFilter =- unlessImported name importFilter $ \filepath contents -> do- state <- get- reader <- ask- result <- liftIO $ compileToAst filepath reader state compileModule contents- case result of- Right (stmts,state) -> do- imports <- filterM importFilter $ stateExports state- modify $ \s -> s { stateFayToJs = stateFayToJs state- , stateJsToFay = stateJsToFay state- , stateImported = stateImported state- , stateLocalScope = S.empty- , stateModuleScope = bindAsLocals imports (stateModuleScope s)- }- return stmts- Left err -> throwError err--unlessImported :: ModuleName- -> (QName -> Compile Bool)- -> (FilePath -> String -> Compile [JsStmt])- -> Compile [JsStmt]-unlessImported "Language.Fay.Types" _ _ = return []-unlessImported name importFilter importIt = do- imported <- gets stateImported- case lookup name imported of- Just _ -> do- sec <- gets stateExportsCache- case M.lookup name sec of- Nothing -> throwError $ UnableResolveCachedImport name- Just exports -> do- imports <- filterM importFilter exports- modify $ \s -> s { stateModuleScope = bindAsLocals imports (stateModuleScope s) }- return []- Nothing -> do- dirs <- configDirectoryIncludes <$> config id- (filepath,contents) <- findImport dirs name- res <- importIt filepath contents- exportsCache <- gets stateExports- -- TODO stateImported is already added in initialPass so it is not needed here- -- but one Api test fails if it's removed.- modify $ \s -> s { stateImported = (name,filepath) : imported- , stateExportsCache = M.insert name exportsCache (stateExportsCache s)- }- return res---- | Compile Haskell declaration.-compileDecls :: Bool -> [Decl] -> Compile [JsStmt]-compileDecls toplevel decls =- case decls of- [] -> return []- (TypeSig _ _ sig:bind@PatBind{}:decls) -> appendM (scoped (compilePatBind toplevel (Just sig) bind))- (compileDecls toplevel decls)- (decl:decls) -> appendM (scoped (compileDecl toplevel decl))- (compileDecls toplevel decls)-- where appendM m n = do x <- m- xs <- n- return (x ++ xs)- scoped = if toplevel then withScope else id---- | Compile a declaration.-compileDecl :: Bool -> Decl -> Compile [JsStmt]-compileDecl toplevel decl =- case decl of- pat@PatBind{} -> compilePatBind toplevel Nothing pat- FunBind matches -> compileFunCase toplevel matches- DataDecl _ DataType _ _ _ constructors _ -> compileDataDecl toplevel decl constructors- GDataDecl _ DataType _l _i _v _n decls _ -> compileDataDecl toplevel decl (map convertGADT decls)- -- Just ignore type aliases and signatures.- TypeDecl{} -> return []- TypeSig{} -> return []- InfixDecl{} -> return []- ClassDecl{} -> return []- InstDecl{} -> return [] -- FIXME: Ignore.- DerivDecl{} -> return []- _ -> throwError (UnsupportedDeclaration decl)--instance CompilesTo Decl [JsStmt] where compileTo = compileDecl True---- | Compile a top-level pattern bind.-compilePatBind :: Bool -> Maybe Type -> Decl -> Compile [JsStmt]-compilePatBind toplevel sig pat =- case pat of- PatBind srcloc (PVar ident) Nothing (UnGuardedRhs rhs) (BDecls []) ->- case ffiExp rhs of- Just formatstr -> case sig of- Just sig -> compileFFI srcloc ident formatstr sig- Nothing -> throwError (FfiNeedsTypeSig pat)- _ -> compileUnguardedRhs srcloc toplevel ident rhs- PatBind srcloc (PVar ident) Nothing (UnGuardedRhs rhs) bdecls -> do- compileUnguardedRhs srcloc toplevel ident (Let bdecls rhs)- _ -> throwError (UnsupportedDeclaration pat)-- where ffiExp (App (Var (UnQual (Ident "ffi"))) (Lit (String formatstr))) = Just formatstr- ffiExp _ = Nothing---- | Compile a normal simple pattern binding.-compileUnguardedRhs :: SrcLoc -> Bool -> Name -> Exp -> Compile [JsStmt]-compileUnguardedRhs srcloc toplevel ident rhs = do- unless toplevel $ bindVar ident- withScope $ do- body <- compileExp rhs- bind <- bindToplevel srcloc toplevel ident (thunk body)- return [bind]--convertGADT :: GadtDecl -> QualConDecl-convertGADT d =- case d of- GadtDecl srcloc name typ -> QualConDecl srcloc tyvars context- (ConDecl name (convertFunc typ))- where tyvars = []- context = []- convertFunc (TyCon _) = []- convertFunc (TyFun x xs) = UnBangedTy x : convertFunc xs- convertFunc (TyParen x) = convertFunc x- convertFunc _ = []---- | Compile a data declaration.-compileDataDecl :: Bool -> Decl -> [QualConDecl] -> Compile [JsStmt]-compileDataDecl toplevel _decl constructors =- fmap concat $- forM constructors $ \(QualConDecl srcloc _ _ condecl) ->- case condecl of- ConDecl name types -> do- let fields = map (Ident . ("slot"++) . show . fst) . zip [1 :: Integer ..] $ types- fields' = (zip (map return fields) types)- cons <- makeConstructor name fields- func <- makeFunc name fields- emitFayToJs name fields'- emitJsToFay name fields'- return [cons, func]- InfixConDecl t1 name t2 -> do- let slots = ["slot1","slot2"]- fields = zip (map return slots) [t1, t2]- cons <- makeConstructor name slots- func <- makeFunc name slots- emitFayToJs name fields- emitJsToFay name fields- return [cons, func]- RecDecl name fields' -> do- let fields = concatMap fst fields'- cons <- makeConstructor name fields- func <- makeFunc name fields- funs <- makeAccessors srcloc fields- emitFayToJs name fields'- emitJsToFay name fields'- return (cons : func : funs)-- where- -- Creates a constructor R_RecConstr for a Record- makeConstructor :: Name -> [Name] -> Compile JsStmt- makeConstructor name (map (JsNameVar . UnQual) -> fields) = do- qname <- qualify name- emitExport (EVar qname)- return $- JsVar (JsConstructor qname) $- JsFun fields (for fields $ \field -> JsSetProp JsThis field (JsName field))- Nothing-- -- Creates a function to initialize the record by regular application- makeFunc :: Name -> [Name] -> Compile JsStmt- makeFunc name (map (JsNameVar . UnQual) -> fields) = do- let fieldExps = map JsName fields- qname <- qualify name- return $ JsVar (JsNameVar qname) $- foldr (\slot inner -> JsFun [slot] [] (Just inner))- (thunk $ JsNew (JsConstructor qname) fieldExps)- fields-- -- Creates getters for a RecDecl's values- makeAccessors :: SrcLoc -> [Name] -> Compile [JsStmt]- makeAccessors srcloc fields =- forM fields $ \name ->- bindToplevel srcloc- toplevel- name- (JsFun [JsNameVar "x"]- []- (Just (thunk (JsGetProp (force (JsName (JsNameVar "x")))- (JsNameVar (UnQual name))))))---- | Compile a function which pattern matches (causing a case analysis).-compileFunCase :: Bool -> [Match] -> Compile [JsStmt]-compileFunCase _toplevel [] = return []-compileFunCase toplevel matches@(Match srcloc name argslen _ _ _:_) = do- pats <- fmap optimizePatConditions (mapM compileCase matches)- bindVar name- bind <- bindToplevel srcloc- toplevel- name- (foldr (\arg inner -> JsFun [arg] [] (Just inner))- (stmtsThunk (concat pats ++ basecase))- args)- return [bind]- where args = zipWith const uniqueNames argslen-- isWildCardMatch (Match _ _ pats _ _ _) = all isWildCardPat pats-- compileCase :: Match -> Compile [JsStmt]- compileCase match@(Match _ _ pats _ rhs _) = do- withScope $ do- whereDecls' <- whereDecls match- generateScope $ zipWithM (\arg pat -> compilePat (JsName arg) pat []) args pats- generateScope $ mapM compileLetDecl whereDecls'- rhsform <- compileRhs rhs- body <- if null whereDecls'- then return $ either id JsEarlyReturn rhsform- else do- binds <- mapM compileLetDecl whereDecls'- return $ case rhsform of- Right exp ->- (JsEarlyReturn (JsApp (JsFun [] (concat binds) (Just exp)) []))- Left stmt ->- (JsEarlyReturn (JsApp (JsFun [] (concat binds ++ [stmt]) Nothing) []))- foldM (\inner (arg,pat) ->- compilePat (JsName arg) pat inner)- [body]- (zip args pats)-- whereDecls :: Match -> Compile [Decl]- whereDecls (Match _ _ _ _ _ (BDecls decls)) = return decls- whereDecls match = throwError (UnsupportedWhereInMatch match)-- basecase :: [JsStmt]- basecase = if any isWildCardMatch matches- then []- else [throw ("unhandled case in " ++ prettyPrint name)- (JsList (map JsName args))]---- | Compile a right-hand-side expression.-compileRhs :: Rhs -> Compile (Either JsStmt JsExp)-compileRhs (UnGuardedRhs exp) = Right <$> compileExp exp-compileRhs (GuardedRhss rhss) = Left <$> compileGuards rhss---- | Compile guards-compileGuards :: [GuardedRhs] -> Compile JsStmt-compileGuards ((GuardedRhs _ (Qualifier (Var (UnQual (Ident "otherwise"))):_) exp):_) =- (\e -> JsIf (JsLit (JsBool True)) [JsEarlyReturn e] []) <$> compileExp exp-compileGuards (GuardedRhs _ (Qualifier guard:_) exp : rest) =- makeIf <$> fmap force (compileExp guard)- <*> compileExp exp- <*> if null rest then (return []) else do- gs' <- compileGuards rest- return [gs']- where makeIf gs e gss = JsIf gs [JsEarlyReturn e] gss--compileGuards rhss = throwError . UnsupportedRhs . GuardedRhss $ rhss---- | Compile Haskell expression.-compileExp :: Exp -> Compile JsExp-compileExp exp =- case exp of- Paren exp -> compileExp exp- Var qname -> compileVar qname- Lit lit -> compileLit lit- App exp1 exp2 -> compileApp exp1 exp2- NegApp exp -> compileNegApp exp- InfixApp exp1 op exp2 -> compileInfixApp exp1 op exp2- Let (BDecls decls) exp -> compileLet decls exp- List [] -> return JsNull- List xs -> compileList xs- Tuple xs -> compileList xs- If cond conseq alt -> compileIf cond conseq alt- Case exp alts -> compileCase exp alts- Con (UnQual (Ident "True")) -> return (JsLit (JsBool True))- Con (UnQual (Ident "False")) -> return (JsLit (JsBool False))- Con qname -> compileVar qname- Do stmts -> compileDoBlock stmts- Lambda _ pats exp -> compileLambda pats exp- LeftSection e o -> compileExp =<< desugarLeftSection e o- RightSection o e -> compileExp =<< desugarRightSection o e- EnumFrom i -> compileEnumFrom i- EnumFromTo i i' -> compileEnumFromTo i i'- EnumFromThen a b -> compileEnumFromThen a b- EnumFromThenTo a b z -> compileEnumFromThenTo a b z- RecConstr name fieldUpdates -> compileRecConstr name fieldUpdates- RecUpdate rec fieldUpdates -> updateRec rec fieldUpdates- ListComp exp stmts -> compileExp =<< desugarListComp exp stmts- ExpTypeSig _ e _ -> compileExp e-- exp -> throwError (UnsupportedExpression exp)--instance CompilesTo Exp JsExp where compileTo = compileExp--compileVar :: QName -> Compile JsExp-compileVar qname = do- qname <- resolveName qname- return (JsName (JsNameVar qname))---- | Compile simple application.-compileApp :: Exp -> Exp -> Compile JsExp-compileApp exp1 exp2 = do- flattenApps <- config configFlattenApps- if flattenApps then method2 else method1- where- -- Method 1:- -- In this approach code ends up looking like this:- -- a(a(a(a(a(a(a(a(a(a(L)(c))(b))(0))(0))(y))(t))(a(a(F)(3*a(a(d)+a(a(f)/20))))*a(a(f)/2)))(140+a(f)))(y))(t)})- -- Which might be OK for speed, but increases the JS stack a fair bit.- method1 =- JsApp <$> (forceFlatName <$> compileExp exp1)- <*> fmap return (compileExp exp2)- forceFlatName name = JsApp (JsName JsForce) [name]-- -- Method 2:- -- In this approach code ends up looking like this:- -- d(O,a,b,0,0,B,w,e(d(I,3*e(e(c)+e(e(g)/20))))*e(e(g)/2),140+e(g),B,w)}),d(K,g,e(c)+0.05))- -- Which should be much better for the stack and readability, but probably not great for speed.- method2 = fmap flatten $- JsApp <$> compileExp exp1- <*> fmap return (compileExp exp2)- flatten (JsApp op args) =- case op of- JsApp l r -> JsApp l (r ++ args)- _ -> JsApp (JsName JsApply) (op : args)- flatten x = x---- | Compile a negate application-compileNegApp :: Exp -> Compile JsExp-compileNegApp e = JsNegApp . force <$> compileExp e---- | Compile an infix application, optimizing the JS cases.-compileInfixApp :: Exp -> QOp -> Exp -> Compile JsExp-compileInfixApp exp1 ap exp2 = do- qname <- resolveName op- case qname of- -- We can optimize prim ops. :-)- Qual "Fay$" _- | prettyPrint ap `elem` words "* + - / < > || &&" -> do- e1 <- compileExp exp1- e2 <- compileExp exp2- fn <- compileExp (Var op)- return $ JsApp (JsApp (force fn) [force e1]) [force e2]- _ -> compileExp (App (App (Var op) exp1) exp2)-- where op = getOp ap- getOp (QVarOp op) = op- getOp (QConOp op) = op---- | Compile a list expression.-compileList :: [Exp] -> Compile JsExp-compileList xs = do- exps <- mapM compileExp xs- return (makeList exps)--makeList :: [JsExp] -> JsExp-makeList exps = (JsApp (JsName (JsBuiltIn "list")) [JsList exps])---- | Compile an if.-compileIf :: Exp -> Exp -> Exp -> Compile JsExp-compileIf cond conseq alt =- JsTernaryIf <$> fmap force (compileExp cond)- <*> compileExp conseq- <*> compileExp alt---- | Compile a lambda.-compileLambda :: [Pat] -> Exp -> Compile JsExp-compileLambda pats exp = do- withScope $ do- generateScope $ generateStatements JsNull- exp <- compileExp exp- stmts <- generateStatements exp- case stmts of- [JsEarlyReturn fun@JsFun{}] -> return fun- _ -> error "Unexpected statements in compileLambda"-- where unhandledcase = throw "unhandled case" . JsName- allfree = all isWildCardPat pats- generateStatements exp =- foldM (\inner (param,pat) -> do- stmts <- compilePat (JsName param) pat inner- return [JsEarlyReturn (JsFun [param] (stmts ++ [unhandledcase param | not allfree]) Nothing)])- [JsEarlyReturn exp]- (reverse (zip uniqueNames pats))---- | Desugar list comprehensions.-desugarListComp :: Exp -> [QualStmt] -> Compile Exp-desugarListComp e [] =- return (List [ e ])-desugarListComp e (QualStmt (Generator loc p e2) : stmts) = do- nested <- desugarListComp e stmts- withScopedTmpName $ \f ->- return (Let (BDecls [ FunBind [- Match loc f [ p ] Nothing (UnGuardedRhs nested) (BDecls []),- Match loc f [ PWildCard ] Nothing (UnGuardedRhs (List [])) (BDecls [])- ]]) (App (App (Var (UnQual (Ident "concatMap"))) (Var (UnQual f))) e2))-desugarListComp e (QualStmt (Qualifier e2) : stmts) = do- nested <- desugarListComp e stmts- return (If e2 nested (List []))-desugarListComp e (QualStmt (LetStmt bs) : stmts) = do- nested <- desugarListComp e stmts- return (Let bs nested)-desugarListComp _ (s : _ ) =- throwError (UnsupportedQualStmt s)---- | Desugar left sections to lambdas.-desugarLeftSection :: Exp -> QOp -> Compile Exp-desugarLeftSection e o = withScopedTmpName $ \tmp ->- return (Lambda undefined [PVar tmp] (InfixApp e o (Var (UnQual tmp))))---- | Desugar left sections to lambdas.-desugarRightSection :: QOp -> Exp -> Compile Exp-desugarRightSection o e = withScopedTmpName $ \tmp ->- return (Lambda undefined [PVar tmp] (InfixApp (Var (UnQual tmp)) o e))---- | Compile case expressions.-compileCase :: Exp -> [Alt] -> Compile JsExp-compileCase exp alts = do- exp <- compileExp exp- withScopedTmpJsName $ \tmpName -> do- pats <- fmap optimizePatConditions $ mapM (compilePatAlt (JsName tmpName)) alts- return $- JsApp (JsFun [tmpName]- (concat pats)- (if any isWildCardAlt alts- then Nothing- else Just (throwExp "unhandled case" (JsName tmpName))))- [exp]---- | Compile a do block.-compileDoBlock :: [Stmt] -> Compile JsExp-compileDoBlock stmts = do- doblock <- foldM compileStmt Nothing (reverse stmts)- maybe (throwError EmptyDoBlock) compileExp doblock---- | Compile a statement of a do block.-compileStmt :: Maybe Exp -> Stmt -> Compile (Maybe Exp)-compileStmt inner stmt =- case inner of- Nothing -> initStmt- Just inner -> subsequentStmt inner-- where initStmt =- case stmt of- Qualifier exp -> return (Just exp)- LetStmt{} -> throwError LetUnsupported- _ -> throwError InvalidDoBlock-- subsequentStmt inner =- case stmt of- Generator loc pat exp -> compileGenerator loc pat inner exp- Qualifier exp -> return (Just (InfixApp exp- (QVarOp (UnQual (Symbol ">>")))- inner))- LetStmt (BDecls binds) -> return (Just (Let (BDecls binds) inner))- LetStmt _ -> throwError LetUnsupported- RecStmt{} -> throwError RecursiveDoUnsupported-- compileGenerator srcloc pat inner exp = do- let body = Lambda srcloc [pat] inner- return (Just (InfixApp exp- (QVarOp (UnQual (Symbol ">>=")))- body))---- | Compile the given pattern against the given expression.-compilePatAlt :: JsExp -> Alt -> Compile [JsStmt]-compilePatAlt exp alt@(Alt _ pat rhs wheres) = case wheres of- BDecls (_ : _) -> throwError (UnsupportedWhereInAlt alt)- IPBinds (_ : _) -> throwError (UnsupportedWhereInAlt alt)- _ -> withScope $ do- generateScope $ compilePat exp pat []- alt <- compileGuardedAlt rhs- compilePat exp pat [alt]---- | Compile the given pattern against the given expression.-compilePat :: JsExp -> Pat -> [JsStmt] -> Compile [JsStmt]-compilePat exp pat body =- case pat of- PVar name -> compilePVar name exp body- PApp cons pats -> compilePApp cons pats exp body- PLit literal -> compilePLit exp literal body- PParen pat -> compilePat exp pat body- PWildCard -> return body- pat@PInfixApp{} -> compileInfixPat exp pat body- PList pats -> compilePList pats body exp- PTuple pats -> compilePList pats body exp- PAsPat name pat -> compilePAsPat exp name pat body- PRec name pats -> compilePatFields exp name pats body- pat -> throwError (UnsupportedPattern pat)---- | Compile a pattern variable e.g. x.-compilePVar :: Name -> JsExp -> [JsStmt] -> Compile [JsStmt]-compilePVar name exp body = do- bindVar name- return $ JsVar (JsNameVar (UnQual name)) exp : body---- | Compile a record field pattern.-compilePatFields :: JsExp -> QName -> [PatField] -> [JsStmt] -> Compile [JsStmt]-compilePatFields exp name pats body = do- c <- liftM (++ body) (compilePats' [] pats)- qname <- resolveName name- return [JsIf (force exp `JsInstanceOf` JsConstructor qname) c []]- where -- compilePats' collects field names that had already been matched so that- -- wildcard generates code for the rest of the fields.- compilePats' :: [QName] -> [PatField] -> Compile [JsStmt]- compilePats' names (PFieldPun name:xs) =- compilePats' names (PFieldPat (UnQual name) (PVar name):xs)-- compilePats' names (PFieldPat fieldname (PVar varName):xs) = do- r <- compilePats' (fieldname : names) xs- bindVar varName- return $ JsVar (JsNameVar (UnQual varName))- (JsGetProp (force exp) (JsNameVar fieldname))- : r -- TODO: think about this force call-- compilePats' names (PFieldWildcard:xs) = do- records <- liftM stateRecords get- let fields = fromJust (lookup name records)- fields' = fields \\ names- f <- mapM (\fieldName -> do bindVar (unQual fieldName)- return (JsVar (JsNameVar fieldName)- (JsGetProp (force exp) (JsNameVar fieldName))))- fields'- r <- compilePats' names xs- return $ f ++ r-- compilePats' _ [] = return []-- compilePats' _ (pat:_) = throwError (UnsupportedFieldPattern pat)-- unQual (Qual _ n) = n- unQual (UnQual n) = n- unQual Special{} = error "Trying to unqualify a Special..."---- | Compile a literal value from a pattern match.-compilePLit :: JsExp -> Literal -> [JsStmt] -> Compile [JsStmt]-compilePLit exp literal body = do- lit <- compileLit literal- return [JsIf (equalExps exp lit)- body- []]-- where -- Equality test for two expressions, with some optimizations.- equalExps :: JsExp -> JsExp -> JsExp- equalExps a b- | isConstant a && isConstant b = JsEq a b- | isConstant a = JsEq a (force b)- | isConstant b = JsEq (force a) b- | otherwise =- JsApp (JsName (JsBuiltIn "equal")) [a,b]---- | Compile as binding in pattern match-compilePAsPat :: JsExp -> Name -> Pat -> [JsStmt] -> Compile [JsStmt]-compilePAsPat exp name pat body = do- bindVar name- x <- compilePat exp pat body- return ([JsVar (JsNameVar (UnQual name)) exp] ++ x)---- | Compile a record construction with named fields--- | GHC will warn on uninitialized fields, they will be undefined in JS.-compileRecConstr :: QName -> [FieldUpdate] -> Compile JsExp-compileRecConstr name fieldUpdates = do- -- var obj = new $_Type()- qname <- resolveName name- let record = JsVar (JsNameVar name) (JsNew (JsConstructor qname) [])- setFields <- liftM concat (forM fieldUpdates (updateStmt name))- return $ JsApp (JsFun [] (record:setFields) (Just (JsName (JsNameVar name)))) []- where updateStmt :: QName -> FieldUpdate -> Compile [JsStmt]- updateStmt o (FieldUpdate field value) = do- exp <- compileExp value- return [JsSetProp (JsNameVar o) (JsNameVar field) exp]- updateStmt name FieldWildcard = do- records <- liftM stateRecords get- let fields = fromJust (lookup name records)- return (map (\fieldName -> JsSetProp (JsNameVar name)- (JsNameVar fieldName)- (JsName (JsNameVar fieldName)))- fields)- -- TODO: FieldPun- -- I couldn't find a code that generates (FieldUpdate (FieldPun ..))- updateStmt _ u = error ("updateStmt: " ++ show u)--updateRec :: Exp -> [FieldUpdate] -> Compile JsExp-updateRec rec fieldUpdates = do- record <- force <$> compileExp rec- let copyName = UnQual (Ident "$_record_to_update")- copy = JsVar (JsNameVar copyName)- (JsRawExp ("Object.create(" ++ printJSString record ++ ")"))- setFields <- forM fieldUpdates (updateExp copyName)- return $ JsApp (JsFun [] (copy:setFields) (Just (JsName (JsNameVar copyName)))) []- where updateExp :: QName -> FieldUpdate -> Compile JsStmt- updateExp copyName (FieldUpdate field value) =- JsSetProp (JsNameVar copyName) (JsNameVar field) <$> compileExp value- updateExp copyName (FieldPun name) =- -- let a = 1 in C {a}- return $ JsSetProp (JsNameVar copyName)- (JsNameVar (UnQual name))- (JsName (JsNameVar (UnQual name)))- -- TODO: FieldWildcard- -- I also couldn't find a code that generates (FieldUpdate FieldWildCard)- updateExp _ FieldWildcard = error "unsupported update: FieldWildcard"---- | Compile a pattern application.-compilePApp :: QName -> [Pat] -> JsExp -> [JsStmt] -> Compile [JsStmt]-compilePApp cons pats exp body = do- let forcedExp = force exp- let boolIf b = return [JsIf (JsEq forcedExp (JsLit (JsBool b))) body []]- case cons of- -- Special-casing on the booleans.- "True" -> boolIf True- "False" -> boolIf False- -- Everything else, generic:- _ -> do- rf <- fmap (lookup cons) (gets stateRecords)- let recordFields =- fromMaybe- (error $ "Constructor '" ++ prettyPrint cons ++- "' was not found in stateRecords, did you try running this through GHC first?")- rf- substmts <- foldM (\body (field,pat) ->- compilePat (JsGetProp forcedExp (JsNameVar field)) pat body)- body- (reverse (zip recordFields pats))- qcons <- resolveName cons- return [JsIf (forcedExp `JsInstanceOf` JsConstructor qcons)- substmts- []]---- | Compile a pattern list.-compilePList :: [Pat] -> [JsStmt] -> JsExp -> Compile [JsStmt]-compilePList [] body exp =- return [JsIf (JsEq (force exp) JsNull) body []]-compilePList pats body exp = do- let forcedExp = force exp- stmts <- foldM (\body (i,pat) -> compilePat (JsApp (JsName (JsBuiltIn "index"))- [JsLit (JsInt i),forcedExp])- pat- body)- body- (reverse (zip [0..] pats))- let patsLen = JsLit (JsInt (length pats))- return [JsIf (JsApp (JsName (JsBuiltIn "listLen")) [forcedExp,patsLen])- stmts- []]---- | Compile an infix pattern (e.g. cons and tuples.)-compileInfixPat :: JsExp -> Pat -> [JsStmt] -> Compile [JsStmt]-compileInfixPat exp pat@(PInfixApp left (Special cons) right) body =- case cons of- Cons -> do- withScopedTmpJsName $ \tmpName -> do- let forcedExp = JsName tmpName- x = JsGetProp forcedExp (JsNameVar "car")- xs = JsGetProp forcedExp (JsNameVar "cdr")- rightMatch <- compilePat xs right body- leftMatch <- compilePat x left rightMatch- return [JsVar tmpName (force exp)- ,JsIf (JsInstanceOf forcedExp (JsBuiltIn "Cons"))- leftMatch- []]- _ -> throwError (UnsupportedPattern pat)-compileInfixPat _ pat _ = throwError (UnsupportedPattern pat)---- | Compile a guarded alt.-compileGuardedAlt :: GuardedAlts -> Compile JsStmt-compileGuardedAlt alt =- case alt of- UnGuardedAlt exp -> JsEarlyReturn <$> compileExp exp- GuardedAlts alts -> compileGuards (map altToRhs alts)- where- altToRhs (GuardedAlt l s e) = GuardedRhs l s e---- | Compile a let expression.-compileLet :: [Decl] -> Exp -> Compile JsExp-compileLet decls exp = do- withScope $ do- generateScope $ mapM compileLetDecl decls- binds <- mapM compileLetDecl decls- body <- compileExp exp- return (JsApp (JsFun [] (concat binds) (Just body)) [])---- | Compile let declaration.-compileLetDecl :: Decl -> Compile [JsStmt]-compileLetDecl decl = do- v <- case decl of- decl@PatBind{} -> compileDecls False [decl]- decl@FunBind{} -> compileDecls False [decl]- TypeSig{} -> return []- _ -> throwError (UnsupportedLetBinding decl)- return v---- | Compile Haskell literal.-compileLit :: Literal -> Compile JsExp-compileLit lit =- case lit of- Char ch -> return (JsLit (JsChar ch))- Int integer -> return (JsLit (JsInt (fromIntegral integer))) -- FIXME:- Frac rational -> return (JsLit (JsFloating (fromRational rational)))- -- TODO: Use real JS strings instead of array, probably it will- -- lead to the same result.- String string -> return (JsApp (JsName (JsBuiltIn "list"))- [JsLit (JsStr string)])- lit -> throwError (UnsupportedLiteral lit)---- | Maximum number of elements to allow in strict list representation--- of arithmetic sequences.-maxStrictASLen :: Int-maxStrictASLen = 10---- | Compile [e1..] arithmetic sequences.-compileEnumFrom :: Exp -> Compile JsExp-compileEnumFrom i = do- e <- compileExp i- name <- resolveName "enumFrom"- return (JsApp (JsName (JsNameVar name)) [e])---- | Compile [e1..e3] arithmetic sequences.-compileEnumFromTo :: Exp -> Exp -> Compile JsExp-compileEnumFromTo i i' = do- f <- compileExp i- t <- compileExp i'- name <- resolveName "enumFromTo"- cfg <- config id- return $ case optEnumFromTo cfg f t of- Just s -> s- _ -> JsApp (JsApp (JsName (JsNameVar name)) [f]) [t]---- | Optimize short literal [e1..e3] arithmetic sequences.-optEnumFromTo :: CompileConfig -> JsExp -> JsExp -> Maybe JsExp-optEnumFromTo cfg (JsLit f) (JsLit t) =- if configOptimize cfg- then case (f,t) of- (JsInt fl, JsInt tl) -> strict JsInt fl tl- (JsFloating fl, JsFloating tl) -> strict JsFloating fl tl- _ -> Nothing- else Nothing- where strict :: (Enum a, Ord a, Num a) => (a -> JsLit) -> a -> a -> Maybe JsExp- strict litfn f t =- if fromEnum t - fromEnum f < maxStrictASLen- then Just . makeList . map (JsLit . litfn) $ Stdlib.enumFromTo f t- else Nothing-optEnumFromTo _ _ _ = Nothing---- | Compile [e1,e2..] arithmetic sequences.-compileEnumFromThen :: Exp -> Exp -> Compile JsExp-compileEnumFromThen a b = do- fr <- compileExp a- th <- compileExp b- name <- resolveName "enumFromThen"- return (JsApp (JsApp (JsName (JsNameVar name)) [fr]) [th])---- | Compile [e1,e2..e3] arithmetic sequences.-compileEnumFromThenTo :: Exp -> Exp -> Exp -> Compile JsExp-compileEnumFromThenTo a b z = do- fr <- compileExp a- th <- compileExp b- to <- compileExp z- name <- resolveName "enumFromThenTo"- cfg <- config id- return $ case optEnumFromThenTo cfg fr th to of- Just s -> s- _ -> JsApp (JsApp (JsApp (JsName (JsNameVar name)) [fr]) [th]) [to]---- | Optimize short literal [e1,e2..e3] arithmetic sequences.-optEnumFromThenTo :: CompileConfig -> JsExp -> JsExp -> JsExp -> Maybe JsExp-optEnumFromThenTo cfg (JsLit fr) (JsLit th) (JsLit to) =- if configOptimize cfg- then case (fr,th,to) of- (JsInt frl, JsInt thl, JsInt tol) -> strict JsInt frl thl tol- (JsFloating frl, JsFloating thl, JsFloating tol) -> strict JsFloating frl thl tol- _ -> Nothing- else Nothing- where strict :: (Enum a, Ord a, Num a) => (a -> JsLit) -> a -> a -> a -> Maybe JsExp- strict litfn fr th to =- if (fromEnum to - fromEnum fr) `div`- (fromEnum th - fromEnum fr) + 1 < maxStrictASLen- then Just . makeList . map (JsLit . litfn) $ Stdlib.enumFromThenTo fr th to- else Nothing-optEnumFromThenTo _ _ _ _ = Nothing
− src/Language/Fay/Compiler/FFI.hs
@@ -1,322 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE ViewPatterns #-}-{-# OPTIONS -Wall #-}---- | Compiling the FFI support.--module Language.Fay.Compiler.FFI- (emitFayToJs- ,emitJsToFay- ,compileFFI- ,jsToFayDispatcher- ,fayToJsDispatcher)- where--import Language.Fay.Compiler.Misc-import Language.Fay.Print (printJSString)-import Language.Fay.Types--import Control.Monad.Error-import Control.Monad.State-import Data.Char-import Data.List-import Data.Maybe-import Language.ECMAScript3.Parser as JS-import Language.ECMAScript3.Syntax-import Language.Haskell.Exts (prettyPrint)-import Language.Haskell.Exts.Syntax-import Prelude hiding (exp)-import Data.Generics.Schemes-import Safe---- | Compile an FFI call.-compileFFI :: SrcLoc -- ^ Location of the original FFI decl.- -> Name -- ^ Name of the to-be binding.- -> String -- ^ The format string.- -> Type -- ^ Type signature.- -> Compile [JsStmt]-compileFFI srcloc name formatstr sig = do- inner <- formatFFI formatstr (zip params funcFundamentalTypes)- case JS.parse JS.parseExpression (prettyPrint name) (printJSString (wrapReturn inner)) of- Left err -> throwError (FfiFormatInvalidJavaScript srcloc inner (show err))- Right exp -> do- config' <- config id- when (configGClosure config') $ warnDotUses srcloc inner exp- fmap return (bindToplevel srcloc True name (body inner))-- where body inner = foldr wrapParam (wrapReturn inner) params- wrapParam pname inner = JsFun [pname] [] (Just inner)- params = zipWith const uniqueNames [1..typeArity sig]- wrapReturn inner = thunk $- case lastMay funcFundamentalTypes of- -- Returns a “pure” value;- Just{} -> jsToFay SerializeAnywhere returnType (JsRawExp inner)- -- Base case:- Nothing -> JsRawExp inner- funcFundamentalTypes = functionTypeArgs sig- returnType = last funcFundamentalTypes---- | Warn about uses of naked x.y which will not play nicely with Google Closure.-warnDotUses :: SrcLoc -> String -> ParsedExpression -> Compile ()-warnDotUses srcloc string expr =- when anyrefs $- warn $ printSrcLoc srcloc ++ ":\nDot ref syntax used in FFI JS code: " ++ string-- where anyrefs = not (null (listify dotref expr)) ||- not (null (listify ldot expr))-- dotref :: ParsedExpression -> Bool- dotref x = case x of- DotRef _ (VarRef _ (Id _ name)) _- | elem name globalNames -> False- DotRef{} -> True- _ -> False-- ldot :: LValue SourcePos -> Bool- ldot x =- case x of- LDot _ (VarRef _ (Id _ name)) _- | elem name globalNames -> False- LDot{} -> True- _ -> False-- globalNames = ["Math","console","JSON"]---- Make a Fay→JS encoder.-emitFayToJs :: Name -> [([Name],BangType)] -> Compile ()-emitFayToJs name (explodeFields -> fieldTypes) = do- qname <- qualify name- modify $ \s -> s { stateFayToJs = translator qname : stateFayToJs s }-- where- translator qname =- JsIf (JsInstanceOf (JsName transcodingObjForced) (JsConstructor qname))- (obj : fieldStmts (zip [0..] fieldTypes) ++ [ret])- []-- obj :: JsStmt- obj = JsVar obj_ $- JsObj [("instance",JsLit (JsStr (printJSString name)))]-- fieldStmts :: [(Int,(Name,BangType))] -> [JsStmt]- fieldStmts [] = []- fieldStmts ((i,fieldType):fts) =- (JsVar obj_v field) :- (JsIf (JsNeq JsUndefined (JsName obj_v))- [JsSetPropExtern obj_ decl (JsName obj_v)]- []) :- fieldStmts fts- where- obj_v = JsNameVar (UnQual (Ident $ "obj_" ++ d))- decl = JsNameVar (UnQual (Ident d))- (d, field) = declField i fieldType-- obj_ = JsNameVar (UnQual (Ident "obj_"))-- ret :: JsStmt- ret = JsEarlyReturn (JsName obj_)-- -- Declare/encode Fay→JS field- declField :: Int -> (Name,BangType) -> (String,JsExp)- declField i (fname,typ) =- (prettyPrint fname- ,fayToJs (case argType (bangType typ) of- known -> typeRep (SerializeUserArg i) known)- (force (JsGetProp (JsName transcodingObjForced)- (JsNameVar (UnQual fname)))))--transcodingObj :: JsName-transcodingObj = JsNameVar "obj"--transcodingObjForced :: JsName-transcodingObjForced = JsNameVar "_obj"---- | Get arg types of a function type.-functionTypeArgs :: Type -> [FundamentalType]-functionTypeArgs t =- case t of- TyForall _ _ i -> functionTypeArgs i- TyFun a b -> argType a : functionTypeArgs b- TyParen st -> functionTypeArgs st- r -> [argType r]---- | Convert a Haskell type to an internal FFI representation.-argType :: Type -> FundamentalType-argType t = case t of- TyCon "String" -> StringType- TyCon "Double" -> DoubleType- TyCon "Int" -> IntType- TyCon "Bool" -> BoolType- TyApp (TyCon "Ptr") _ -> PtrType- TyApp (TyCon "Automatic") _ -> Automatic- TyApp (TyCon "Defined") a -> Defined (argType a)- TyApp (TyCon "Nullable") a -> Nullable (argType a)- TyApp (TyCon "Fay") a -> JsType (argType a)- TyFun x xs -> FunctionType (argType x : functionTypeArgs xs)- TyList x -> ListType (argType x)- TyTuple _ xs -> TupleType (map argType xs)- TyParen st -> argType st- TyApp op arg -> userDefined (reverse (arg : expandApp op))- _ ->- -- No semantic point to this, merely to avoid GHC's broken- -- warning.- case t of- TyCon (UnQual user) -> UserDefined user []- _ -> UnknownType---- | Extract the type.-bangType :: BangType -> Type-bangType typ = case typ of- BangedTy ty -> ty- UnBangedTy ty -> ty- UnpackedTy ty -> ty---- | Expand a type application.-expandApp :: Type -> [Type]-expandApp (TyParen t) = expandApp t-expandApp (TyApp op arg) = arg : expandApp op-expandApp x = [x]---- | Generate a user-defined type.-userDefined :: [Type] -> FundamentalType-userDefined (TyCon (UnQual name):typs) = UserDefined name (map argType typs)-userDefined _ = UnknownType---- | Translate: JS → Fay.-jsToFay :: SerializeContext -> FundamentalType -> JsExp -> JsExp-jsToFay context typ exp =- JsApp (JsName (JsBuiltIn "jsToFay"))- [typeRep context typ,exp]---- | Translate: Fay → JS.-fayToJs :: JsExp -> JsExp -> JsExp-fayToJs typ exp = JsApp (JsName (JsBuiltIn "fayToJs"))- [typ,exp]---- | Get a JS-representation of a fundamental type for encoding/decoding.-typeRep :: SerializeContext -> FundamentalType -> JsExp-typeRep context typ = case typ of- FunctionType xs -> JsList [JsLit $ JsStr "function",JsList (map (typeRep context) xs)]- JsType x -> JsList [JsLit $ JsStr "action",JsList [typeRep context x]]- ListType x -> JsList [JsLit $ JsStr "list",JsList [typeRep context x]]- TupleType xs -> JsList [JsLit $ JsStr "tuple",JsList (map (typeRep context) xs)]- UserDefined name xs -> JsList [JsLit $ JsStr "user"- ,JsLit $ JsStr (unname name)- ,JsList (zipWith (\t i -> typeRep (setArg i context) t) xs [0..])]- Defined x -> JsList [JsLit $ JsStr "defined",JsList [typeRep context x]]- Nullable x -> JsList [JsLit $ JsStr "nullable",JsList [typeRep context x]]- _ -> nom-- where- setArg i SerializeUserArg{} = SerializeUserArg i- setArg _ c = c- ret = JsList . return . JsLit . JsStr- nom = case typ of- StringType -> ret "string"- DoubleType -> ret "double"- PtrType -> ret "ptr"- Automatic -> ret "automatic"- IntType -> ret "int"- BoolType -> ret "bool"- DateType -> ret "date"- _ ->- case context of- SerializeAnywhere -> ret "unknown"- SerializeUserArg i ->- let args = JsIndex 2 (JsName JsParametrizedType)- thisArg = JsIndex i args- unknown = ret "unknown"- in JsTernaryIf args- (JsTernaryIf thisArg- thisArg- unknown)- unknown---- | Get the arity of a type.-typeArity :: Type -> Int-typeArity t = case t of- TyForall _ _ i -> typeArity i- TyFun _ b -> 1 + typeArity b- TyParen st -> typeArity st- _ -> 0---- | Format the FFI format string with the given arguments.-formatFFI :: String -- ^ The format string.- -> [(JsName,FundamentalType)] -- ^ Arguments.- -> Compile String -- ^ The JS code.-formatFFI formatstr args = go formatstr where- go ('%':'*':xs) = do- these <- mapM inject (zipWith const [1..] args)- rest <- go xs- return (intercalate "," these ++ rest)- go ('%':'%':xs) = do- rest <- go xs- return ('%' : rest)- go ['%'] = throwError FfiFormatIncompleteArg- go ('%':(span isDigit -> (op,xs))) =- case readMay op of- Nothing -> throwError (FfiFormatBadChars op)- Just n -> do- this <- inject n- rest <- go xs- return (this ++ rest)- go (x:xs) = do rest <- go xs- return (x : rest)- go [] = return []-- inject n =- case listToMaybe (drop (n-1) args) of- Nothing -> throwError (FfiFormatNoSuchArg n)- Just (arg,typ) -> do- return (printJSString (fayToJs (typeRep SerializeAnywhere typ) (JsName arg)))--explodeFields :: [([a], t)] -> [(a, t)]-explodeFields = concatMap $ \(names,typ) -> map (,typ) names--fayToJsDispatcher :: [JsStmt] -> JsStmt-fayToJsDispatcher cases =- JsVar (JsBuiltIn "fayToJsUserDefined")- (JsFun [JsNameVar "type",transcodingObj]- (decl ++ cases ++ [baseCase])- Nothing)-- where decl = [JsVar transcodingObjForced- (force (JsName transcodingObj))- ,JsVar (JsNameVar "argTypes")- (JsLookup (JsName (JsNameVar "type"))- (JsLit (JsInt 2)))]- baseCase =- JsEarlyReturn (JsName transcodingObj)--jsToFayDispatcher :: [JsStmt] -> JsStmt-jsToFayDispatcher cases =- JsVar (JsBuiltIn "jsToFayUserDefined")- (JsFun [JsNameVar "type",transcodingObj]- (cases ++ [baseCase])- Nothing)-- where baseCase =- JsEarlyReturn (JsName transcodingObj)---- Make a JS→Fay decoder-emitJsToFay :: Name -> [([Name], BangType)] -> Compile ()-emitJsToFay name (explodeFields -> fieldTypes) = do- qname <- qualify name- modify $ \s -> s { stateJsToFay = translator qname : stateJsToFay s }-- where- translator qname =- JsIf (JsEq (JsGetPropExtern (JsName transcodingObj) "instance")- (JsLit (JsStr (printJSString name))))- [JsEarlyReturn (JsNew (JsConstructor qname)- (zipWith decodeField fieldTypes [0..]))]- []- -- Decode JS→Fay field- decodeField :: (Name,BangType) -> Int -> JsExp- decodeField (fname,typ) i =- jsToFay (SerializeUserArg i)- (argType (bangType typ))- (JsGetPropExtern (JsName transcodingObj)- (prettyPrint fname))
− src/Language/Fay/Compiler/Misc.hs
@@ -1,246 +0,0 @@-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE OverloadedStrings #-}-{-# OPTIONS -Wall -fno-warn-orphans #-}---- | Miscellaneous functions used throughout the compiler.--module Language.Fay.Compiler.Misc where--import qualified Language.Fay.ModuleScope as ModuleScope-import Language.Fay.Types--import System.Process (readProcess)-import Text.ParserCombinators.ReadP (readP_to_S)-import Data.Version (parseVersion)-import Control.Applicative-import Control.Monad.Error-import Control.Monad.Reader-import Control.Monad.State-import Data.List-import qualified Data.Set as S-import Data.Maybe-import Data.String-import Language.Haskell.Exts (ParseResult(..))-import Language.Haskell.Exts.Syntax-import Prelude hiding (exp, mod)-import System.IO---- | Extra the string from an ident.-unname :: Name -> String-unname (Ident str) = str-unname _ = error "Expected ident from uname." -- FIXME:---- | Make an identifier from the built-in HJ module.-fayBuiltin :: String -> QName-fayBuiltin = Qual (ModuleName "Fay$") . Ident---- | Wrap an expression in a thunk.-thunk :: JsExp -> JsExp--- thunk exp = JsNew (fayBuiltin "Thunk") [JsFun [] [] (Just exp)]-thunk expr =- case expr of- -- JS constants don't need to be in thunks, they're already strict.- JsLit{} -> expr- -- Functions (e.g. lets) used for introducing a new lexical scope- -- aren't necessary inside a thunk. This is a simple aesthetic- -- optimization.- JsApp fun@JsFun{} [] -> JsNew JsThunk [fun]- -- Otherwise make a regular thunk.- _ -> JsNew JsThunk [JsFun [] [] (Just expr)]---- | Wrap an expression in a thunk.-stmtsThunk :: [JsStmt] -> JsExp-stmtsThunk stmts = JsNew JsThunk [JsFun [] stmts Nothing]---- | Generate unique names.-uniqueNames :: [JsName]-uniqueNames = map JsParam [1::Integer ..]---- | Resolve a given maybe-qualified name to a fully qualifed name.-resolveName :: QName -> Compile QName-resolveName special@Special{} = return special-resolveName q@Qual{} = do- env <- gets stateModuleScope- maybe (throwError $ UnableResolveQualified q) return (ModuleScope.resolveName q env)-resolveName u@(UnQual name) = do- names <- gets stateLocalScope- env <- gets stateModuleScope- if S.member name names- then return (UnQual name)- else maybe (qualify name) return (ModuleScope.resolveName u env)---- | Qualify a name for the current module.-qualify :: Name -> Compile QName-qualify name = do- modulename <- gets stateModuleName- return (Qual modulename name)---- | Make a top-level binding.-bindToplevel :: SrcLoc -> Bool -> Name -> JsExp -> Compile JsStmt-bindToplevel srcloc toplevel name expr = do- qname <- (if toplevel then qualify else return . UnQual) name- return (JsMappedVar srcloc (JsNameVar qname) expr)---- | Create a temporary environment and discard it after the given computation.-withModuleScope :: Compile a -> Compile a-withModuleScope m = do- scope <- gets stateModuleScope- value <- m- modify $ \s -> s { stateModuleScope = scope }- return value---- | Create a temporary scope and discard it after the given computation.-withScope :: Compile a -> Compile a-withScope m = do- scope <- gets stateLocalScope- value <- m- modify $ \s -> s { stateLocalScope = scope }- return value---- | Run a compiler and just get the scope information.-generateScope :: Compile a -> Compile ()-generateScope m = do- st <- get- _ <- m- scope <- gets stateLocalScope- put st { stateLocalScope = scope }---- | Bind a variable in the current scope.-bindVar :: Name -> Compile ()-bindVar name = do- modify $ \s -> s { stateLocalScope = S.insert name (stateLocalScope s) }---- | Emit exported names.-emitExport :: ExportSpec -> Compile ()-emitExport spec = case spec of- EVar (UnQual n) -> emitVar n- EVar q@Qual{} -> modify $ \s -> s { stateExports = q : stateExports s }- EThingAll (UnQual name) -> do- emitVar name- r <- lookup (UnQual name) <$> gets stateRecords- maybe (return ()) (mapM_ (emitVar . unQName)) r- EThingWith (UnQual name) ns -> do- emitVar name- mapM_ emitCName ns- EAbs _ -> return () -- Type only, skip- EModuleContents mod ->- mapM_ (emitExport . EVar) =<< ModuleScope.moduleLocals mod <$> gets stateModuleScope- e -> throwError $ UnsupportedExportSpec e- where- emitVar = return . UnQual >=> resolveName >=> emitExport . EVar- emitCName (VarName n) = emitVar n- emitCName (ConName n) = emitVar n- unQName (UnQual u) = u- unQName _ = error "unQName Qual or Special -- should never happen"---- | Force an expression in a thunk.-force :: JsExp -> JsExp-force expr- | isConstant expr = expr- | otherwise = JsApp (JsName JsForce) [expr]---- | Is a JS expression a literal (constant)?-isConstant :: JsExp -> Bool-isConstant JsLit{} = True-isConstant _ = False---- | Extract the string from a qname.--- qname :: QName -> String--- qname (UnQual (Ident str)) = str--- qname (UnQual (Symbol sym)) = jsEncodeName sym--- qname i = error $ "qname: Expected unqualified ident, found: " ++ show i -- FIXME:---- | Deconstruct a parse result (a la maybe, foldr, either).-parseResult :: ((SrcLoc,String) -> b) -> (a -> b) -> ParseResult a -> b-parseResult die ok result = case result of- ParseOk a -> ok a- ParseFailed srcloc msg -> die (srcloc,msg)---- | Get a config option.-config :: (CompileConfig -> a) -> Compile a-config f = asks (f . readerConfig)---- | Optimize pattern matching conditions by merging conditions in common.-optimizePatConditions :: [[JsStmt]] -> [[JsStmt]]-optimizePatConditions = concatMap merge . groupBy sameIf where- sameIf [JsIf cond1 _ _] [JsIf cond2 _ _] = cond1 == cond2- sameIf _ _ = False- merge xs@([JsIf cond _ _]:_) =- [[JsIf cond (concat (optimizePatConditions (map getIfConsequent xs))) []]]- merge noifs = noifs- getIfConsequent [JsIf _ cons _] = cons- getIfConsequent other = other---- | Throw a JS exception.-throw :: String -> JsExp -> JsStmt-throw msg expr = JsThrow (JsList [JsLit (JsStr msg),expr])---- | Throw a JS exception (in an expression).-throwExp :: String -> JsExp -> JsExp-throwExp msg expr = JsThrowExp (JsList [JsLit (JsStr msg),expr])---- | Is an alt a wildcard?-isWildCardAlt :: Alt -> Bool-isWildCardAlt (Alt _ pat _ _) = isWildCardPat pat---- | Is a pattern a wildcard?-isWildCardPat :: Pat -> Bool-isWildCardPat PWildCard{} = True-isWildCardPat PVar{} = True-isWildCardPat _ = False---- | Generate a temporary, SCOPED name for testing conditions and--- such.-withScopedTmpJsName :: (JsName -> Compile a) -> Compile a-withScopedTmpJsName withName = do- depth <- gets stateNameDepth- modify $ \s -> s { stateNameDepth = depth + 1 }- ret <- withName $ JsTmp depth- modify $ \s -> s { stateNameDepth = depth }- return ret---- | Generate a temporary, SCOPED name for testing conditions and--- such. We don't have name tracking yet, so instead we use this.-withScopedTmpName :: (Name -> Compile a) -> Compile a-withScopedTmpName withName = do- depth <- gets stateNameDepth- modify $ \s -> s { stateNameDepth = depth + 1 }- ret <- withName $ Ident $ "$gen" ++ show depth- modify $ \s -> s { stateNameDepth = depth }- return ret---- | Print out a compiler warning.-warn :: String -> Compile ()-warn "" = return ()-warn w = do- shouldWarn <- config configWarn- when shouldWarn . liftIO . hPutStrLn stderr $ "Warning: " ++ w---- | Pretty print a source location.-printSrcLoc :: SrcLoc -> String-printSrcLoc SrcLoc{..} = srcFilename ++ ":" ++ show srcLine ++ ":" ++ show srcColumn--anyM :: Monad m => (a -> m Bool) -> [a] -> m Bool-anyM p l = return . not . null =<< filterM p l--typeToRecs :: QName -> Compile [QName]-typeToRecs typ = fromMaybe [] . lookup typ <$> gets stateRecordTypes--typeToFields :: QName -> Compile [QName]-typeToFields typ = do- allrecs <- gets stateRecords- typerecs <- typeToRecs typ- return . concatMap snd . filter ((`elem` typerecs) . fst) $ allrecs---- | Get the flag used for GHC, this differs between GHC-7.6.0 and--- GHC-everything-else so we need to specially test for that. It's--- lame, but that's random flag name changes for you.-getGhcPackageDbFlag :: IO String-getGhcPackageDbFlag = do- s <- readProcess "ghc" ["--version"] ""- return $- case (mapMaybe readVersion $ words s, readVersion "7.6.0") of- (v:_, Just min') | v > min' -> "-package-db"- _ -> "-package-conf"- where- readVersion = listToMaybe . filter (null . snd) . readP_to_S parseVersion
− src/Language/Fay/Compiler/Optimizer.hs
@@ -1,206 +0,0 @@-{-# OPTIONS -fno-warn-orphans #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE PatternGuards #-}--module Language.Fay.Compiler.Optimizer where--import Control.Applicative-import Control.Arrow (first)-import Control.Monad.Error-import Control.Monad.Writer-import Control.Monad.State-import Data.List-import Data.Maybe-import Language.Fay.Print-import Language.Fay.Types-import Language.Haskell.Exts (QName(..),ModuleName(..),Name(..))-import Language.Haskell.Exts (SrcLoc(..))-import Prelude hiding (exp)---- | The arity of a function. Arity here is defined to be the number--- of arguments that can be directly uncurried from a curried lambda--- abstraction. So \x y z -> if x then (\a -> a) else (\a -> a) has an--- arity of 3, not 4.-type FuncArity = (QName,Int)---- | Optimize monad.-type Optimize = State OptState---- | State.-data OptState = OptState- { optStmts :: [JsStmt]- , optUncurry :: [QName]- }---- | Run an optimizer, which may output additional statements.-runOptimizer :: ([JsStmt] -> Optimize [JsStmt]) -> [JsStmt] -> [JsStmt]-runOptimizer optimizer stmts =- let (newstmts,OptState _ uncurried) = flip runState st $ optimizer stmts- in (newstmts ++ (tco (catMaybes (map (uncurryBinding newstmts) (nub uncurried)))))- where st = OptState stmts []---- | Perform any top-level cross-module optimizations and GO DEEP to--- optimize further.-optimizeToplevel :: [JsStmt] -> Optimize [JsStmt]-optimizeToplevel = stripAndUncurry---- | Perform tail-call optimization.-tco :: [JsStmt] -> [JsStmt]-tco = map inStmt where- inStmt stmt = case stmt of- JsMappedVar srcloc name exp -> JsMappedVar srcloc name (inject name exp)- JsVar name exp -> JsVar name (inject name exp)- e -> e- inject name exp = case exp of- JsFun params [] (Just (JsNew JsThunk [JsFun [] stmts ret])) ->- JsFun params- []- (Just- (JsNew JsThunk- [JsFun []- (optimize params name (stmts ++ [ JsEarlyReturn e | Just e <- [ret] ]))- Nothing]))- _ -> exp- optimize params name stmts = result where- result = let (newstmts,w) = runWriter makeWhile- in if null w- then stmts- else newstmts- makeWhile = do- newstmts <- fmap concat (mapM swap stmts)- return [JsWhile (JsLit (JsBool True)) newstmts]- swap stmt = case stmt of- JsEarlyReturn e- | tailCall e -> do tell [()]- return (rebind e ++ [JsContinue])- | otherwise -> return [stmt]- JsIf p ithen ielse -> do- newithen <- fmap concat (mapM swap ithen)- newielse <- fmap concat (mapM swap ielse)- return [JsIf p newithen newielse]- e -> return [e]- tailCall (JsApp (JsName cname) _) = cname == name- tailCall _ = False- rebind (JsApp _ args) = zipWith go args params where- go arg param = JsUpdate param arg- rebind e = error . show $ e---- | Strip redundant forcing from the whole generated code.-stripAndUncurry :: [JsStmt] -> Optimize [JsStmt]-stripAndUncurry = applyToExpsInStmts stripFuncForces where- stripFuncForces arities exp = case exp of- JsApp (JsName JsForce) [JsName (JsNameVar f)]- | Just _ <- lookup f arities -> return (JsName (JsNameVar f))- JsFun ps stmts body -> do substmts <- mapM stripInStmt stmts- sbody <- maybe (return Nothing) (fmap Just . go) body- return (JsFun ps substmts sbody)- JsApp a b -> do- result <- walkAndStripForces arities exp- case result of- Just strippedExp -> go strippedExp- Nothing -> JsApp <$> go a <*> mapM go b- JsNegApp e -> JsNegApp <$> go e- JsTernaryIf a b c -> JsTernaryIf <$> go a <*> go b <*> go c- JsParen e -> JsParen <$> go e- JsUpdateProp e n a -> JsUpdateProp <$> go e <*> pure n <*> go a- JsList xs -> JsList <$> mapM go xs- JsEq a b -> JsEq <$> go a <*> go b- JsInfix op a b -> JsInfix op <$> go a <*> go b- JsObj xs -> JsObj <$> mapM (\(x,y) -> (x,) <$> go y) xs- JsNew name xs -> JsNew name <$> mapM go xs- e -> return e-- where- go = stripFuncForces arities- stripInStmt = applyToExpsInStmt arities stripFuncForces---- | Strip redundant forcing from an application if possible.-walkAndStripForces :: [FuncArity] -> JsExp -> Optimize (Maybe JsExp)-walkAndStripForces arities = go True [] where- go frst args app = case app of- JsApp (JsName JsForce) [e] -> if frst- then do result <- go False args e- case result of- Nothing -> return Nothing- Just ex -> return (Just (JsApp (JsName JsForce) [ex]))- else go False args e- JsApp op [arg] -> go False (arg:args) op- JsName (JsNameVar f)- | Just arity <- lookup f arities, length args == arity -> do- modify $ \s -> s { optUncurry = f : optUncurry s }- return (Just (JsApp (JsName (JsNameVar (renameUncurried f))) args))- _ -> return Nothing---- | Apply the given function to the top-level expressions in the--- given statements.-applyToExpsInStmts :: ([FuncArity] -> JsExp -> Optimize JsExp) -> [JsStmt] -> Optimize [JsStmt]-applyToExpsInStmts f stmts = mapM (applyToExpsInStmt (collectFuncs stmts) f) stmts---- | Apply the given function to the top-level expressions in the--- given statement.-applyToExpsInStmt :: [FuncArity] -> ([FuncArity] -> JsExp -> Optimize JsExp) -> JsStmt -> Optimize JsStmt-applyToExpsInStmt funcs f stmts = uncurryInStmt stmts where- transform = f funcs- uncurryInStmt stmt = case stmt of- JsMappedVar srcloc name exp -> JsMappedVar srcloc name <$> transform exp- JsVar name exp -> JsVar name <$> transform exp- JsEarlyReturn exp -> JsEarlyReturn <$> transform exp- JsIf op ithen ielse -> JsIf <$> transform op- <*> mapM uncurryInStmt ithen- <*> mapM uncurryInStmt ielse- s -> pure s---- | Collect functions and their arity from the whole codeset.-collectFuncs :: [JsStmt] -> [FuncArity]-collectFuncs = (++ prim) . concat . map collectFunc where- collectFunc (JsMappedVar _ name exp) = collectFunc (JsVar name exp)- collectFunc (JsVar (JsNameVar name) exp) | arity > 0 = [(name,arity)]- where arity = expArity exp- collectFunc _ = []- prim = map (first (Qual (ModuleName "Fay$"))) (unary ++ binary)- unary = map (,1) [Ident "return"]- binary = map ((,2) . Ident)- ["then","bind","mult","mult","add","sub","div"- ,"eq","neq","gt","lt","gte","lte","and","or"]---- | Get the arity of an expression.-expArity :: JsExp -> Int-expArity (JsFun _ _ mexp) = 1 + maybe 0 expArity mexp-expArity _ = 0--test :: IO ()-test = do- let (newstmts,OptState _ uncurried) = flip runState st $ optimizeToplevel stmts- putStrLn $ printJSPretty newstmts- putStrLn $ printJSPretty (catMaybes (map (uncurryBinding newstmts) uncurried))-- where- st = OptState stmts []- stmts = [JsMappedVar (SrcLoc {srcFilename = "", srcLine = 1, srcColumn = 1}) (JsNameVar (Qual (ModuleName "Main") (Ident "sum$uncurried"))) (JsFun [JsParam 1,JsParam 2] [] (Just (JsNew JsThunk [JsFun [] [JsVar (JsNameVar (UnQual (Ident "acc"))) (JsName (JsParam 2)),JsIf (JsEq (JsApp (JsName JsForce) [JsName (JsParam 1)]) (JsLit (JsInt 0))) [JsEarlyReturn (JsName (JsNameVar (UnQual (Ident "acc"))))] [],JsVar (JsNameVar (UnQual (Ident "acc"))) (JsName (JsParam 2)),JsVar (JsNameVar (UnQual (Ident "n"))) (JsName (JsParam 1)),JsEarlyReturn (JsApp (JsName (JsNameVar (Qual (ModuleName "Main") (Ident "sum$uncurried")))) [JsApp (JsName (JsNameVar (Qual (ModuleName "Fay$") (Ident "sub$uncurried")))) [JsApp (JsName JsForce) [JsName (JsNameVar (UnQual (Ident "n")))],JsLit (JsInt 1)],JsApp (JsName (JsNameVar (Qual (ModuleName "Fay$") (Ident "add$uncurried")))) [JsApp (JsName JsForce) [JsName (JsNameVar (UnQual (Ident "acc")))],JsApp (JsName JsForce) [JsName (JsNameVar (UnQual (Ident "n")))]]])] Nothing])))]--uncurryBinding :: [JsStmt] -> QName -> Maybe JsStmt-uncurryBinding stmts qname = listToMaybe (mapMaybe funBinding stmts)- where- funBinding stmt = case stmt of- JsMappedVar srcloc (JsNameVar name) body- | name == qname -> JsMappedVar srcloc (JsNameVar (renameUncurried name)) <$> uncurryIt body- JsVar (JsNameVar name) body- | name == qname -> JsVar (JsNameVar (renameUncurried name)) <$> uncurryIt body- _ -> Nothing-- uncurryIt = Just . go [] where- go args exp = case exp of- JsFun [arg] [] (Just body) -> go (arg : args) body- inner -> JsFun (reverse args) [] (Just inner)---- | Rename an uncurried copy of a curried function.-renameUncurried :: QName -> QName-renameUncurried q = case q of- Qual m n -> Qual m (renameUnQual n)- UnQual n -> UnQual (renameUnQual n)- s -> s- where- renameUnQual n = case n of- Ident nom -> Ident (nom ++ postfix)- Symbol nom -> Symbol (nom ++ postfix)- postfix = "$uncurried"
− src/Language/Fay/Compiler/Packages.hs
@@ -1,115 +0,0 @@--- | Dealing with Cabal packages in Fay's own special way.--module Language.Fay.Compiler.Packages where--import Language.Fay.Types--import Control.Monad-import Data.List-import GHC.Paths-import System.Directory-import System.FilePath-import System.Process.Extra---- | Given a configuration, resolve any packages specified to their--- data file directories for importing the *.hs sources.-resolvePackages :: CompileConfig -> IO CompileConfig-resolvePackages config = do- foldM resolvePackage config (configPackages config)---- | Resolve package.-resolvePackage :: CompileConfig -> String -> IO CompileConfig-resolvePackage config name = do- desc <- describePackage (configPackageConf config) name- case shareDirs desc of- Nothing -> error $ "unable to find share dir of package: " ++ name- Just dirs -> do- mapM_ checkDirExists dirs- return (addConfigDirectoryIncludes dirs config)---- | Describe package with ghc-pkg.------ Weinsworth : Why are you not using the GHC API which would--- provide you this information like in modules like--- Packages which has functions like------ collectIncludeDirs :: [PackageConfig] -> [FilePath]------ and awesome stuff like that. What are you, stupid?------ Batemen : Pretty much. I think this might be a little faster than--- initializing GHC, and using the GHC API adds a lot of--- link time when you use it.------ Weinsworth : Uh huh.------ Batemen: Yeah. Stop looking at me like that.----describePackage :: Maybe FilePath -> String -> IO String-describePackage db name = do- result <- readAllFromProcess ghc_pkg args ""- case result of- Left err -> error $ "ghc-pkg describe error:\n" ++ err- Right (_err,out) -> return out-- where args = concat [["describe",name]- ,["-f" ++ db' | Just db' <- [db]]]---- | Get the share dirs of the package.------ Alright.--- Stop.--- Collaborate and listen.------ You're gonna have to stop scrolling and read this.------ I can't figure out how to get the data-dirs from the package--- description.------ * It doesn't seem to be in the Cabal API's PackageDescription type.--- * It doesn't seem to be in the ghc-pkg description.--- * I can't find out how to read the Cabal configuration. Yeah, I--- could probably find it eventually. Shut up.------ So what I'm doing is parsing the “import-dirs” flag, which--- appears in ghc-pkg's output like this:------ /home/chris/Projects/me/fay-jquery/cabal-dev//lib/fay-jquery-0.1.0.0/ghc-7.4.1------ And I'm going to replace “lib” with “share” and drop the “ghc-*”--- and that, under a *normal* configuration, gives the share--- directory.------ Under an atypical situation, we're going to throw an error and--- you guys will just have to submit a pull request or some code to--- do this better, because I've got better things to be doing, like--- climbing trees, baking cookies and reading books about zombies.----shareDirs :: String -> Maybe [FilePath]-shareDirs desc =- case find (isPrefixOf "import-dirs: ") (lines desc) of- Nothing -> Nothing- Just idirs ->- case words idirs of- -- I'm going to take the first one. If you've got more, just,- -- I hate you.- (_import_dirs:idir:_) -> Just $ [munge idir- ,munge idir </> "src"] -- Yep.- _ -> Nothing-- where munge = joinPath . reverse . swap . dropGhc . reverse . map dropTrailingPathSeparator . splitPath where- dropGhc = drop 1- swap (name_version:"lib":rest) = name_version : "share" : rest- swap paths = error $ "unable to complete munging of the lib dir\- \, see Language.Fay.Compiler.Packages.hs \- \for an explanation: " ++- "\npath was: " ++ joinPath paths---- | Might as well check the dir that we munged to death actually--- exists. -___ --checkDirExists :: FilePath -> IO ()-checkDirExists p = do- don'tFlipOut <- doesDirectoryExist p- unless don'tFlipOut $- error $ "so the directory we munged doesn't exist:\n " ++ p ++- "\nreport a bug, we screwed up."
− src/Language/Fay/Convert.hs
@@ -1,198 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TupleSections #-}-{-# OPTIONS -fno-warn-type-defaults #-}---- | Convert a Haskell value to a (JSON representation of a) Fay value.--module Language.Fay.Convert- (showToFay- ,readFromFay)- where--import Control.Applicative-import Control.Monad-import Control.Monad.State-import Data.Aeson-import Data.Attoparsec.Number-import Data.Char-import Data.Data-import Data.Function-import Data.Generics.Aliases-import Data.HashMap.Strict (HashMap)-import qualified Data.HashMap.Strict as Map-import Data.Maybe-import Data.Text (Text)-import qualified Data.Text as Text-import qualified Data.Vector as Vector-import Numeric-import Safe-import qualified Text.Show.Pretty as Show------------------------------------------------------------------------------------- The conversion functions.---- | Convert a Haskell value to a value representing a Fay value.-showToFay :: Show a => a -> Maybe Value-showToFay = Show.reify >=> convert where- convert value = case value of- -- Special cases- Show.Con "True" _ -> return (Bool True)- Show.Con "False" _ -> return (Bool False)-- -- Objects/records- Show.Con name values -> fmap (Object . Map.fromList . (("instance",string name) :))- (slots values)- Show.Rec name fields -> fmap (Object . Map.fromList . (("instance",string name) :))- (mapM (uncurry keyval) fields)-- -- List types- Show.Tuple values -> fmap (Array . Vector.fromList) (mapM convert values)- Show.List values -> fmap (Array . Vector.fromList) (mapM convert values)-- -- Text types- Show.String chars -> fmap string (readMay chars)- Show.Char char -> fmap (string.return) (readMay char)-- -- Numeric types (everything treated as a double)- Show.Neg{} -> double <|> int- Show.Integer{} -> int- Show.Float{} -> double- Show.Ratio{} -> double- where double = convertDouble value- int = convertInt value-- -- Number converters- convertDouble = fmap (Number . D) . pDouble- convertInt = fmap (Number . I) . pInt-- -- Number parsers- pDouble :: Show.Value -> Maybe Double- pDouble value = case value of- Show.Float str -> getDouble str- Show.Ratio x y -> liftM2 (on (/) fromIntegral) (pInt x) (pInt y)- Show.Neg str -> fmap (* (-1)) (pDouble str)- _ -> Nothing- pInt value = case value of- Show.Integer str -> getInt str- Show.Neg str -> fmap (* (-1)) (pInt str)- _ -> Nothing-- -- Number readers- getDouble :: String -> Maybe Double- getDouble = fmap fst . listToMaybe . readFloat- getInt :: String -> Maybe Integer- getInt = fmap fst . listToMaybe . readInt 10 isDigit charToInt- where charToInt c = fromEnum c - fromEnum '0'-- -- Utilities- string = String . Text.pack- slots = zipWithM keyval (map (("slot"++).show) [1::Int ..])- keyval key val = fmap (Text.pack key,) (convert val)---- | Convert a value representing a Fay value to a Haskell value.--readFromFay :: Data a => Value -> Maybe a-readFromFay value = do- parseData value- `ext1R` parseArray value- `extR` parseDouble value- `extR` parseInt value- `extR` parseBool value- `extR` parseString value- `extR` parseText value---- | Parse a data type or record.-parseData :: Data a => Value -> Maybe a-parseData value = result where- result = getObject value >>= parseObject typ- typ = dataTypeOf (fromJust result)- getObject x =- case x of- Object obj -> return obj- _ -> mzero---- | Parse a data constructor from an object.-parseObject :: Data a => DataType -> HashMap Text Value -> Maybe a-parseObject typ obj = listToMaybe (catMaybes choices) where- choices = map makeConstructor constructors- constructors = dataTypeConstrs typ- makeConstructor cons = do- name <- Map.lookup (Text.pack "instance") obj >>= parseString- guard (showConstr cons == name)- if null fields- then makeSimple obj cons- else makeRecord obj cons fields-- where fields = constrFields cons---- | Make a simple ADT constructor from an object: { "slot1": 1, "slot2": 2} -> Foo 1 2-makeSimple :: Data a => HashMap Text Value -> Constr -> Maybe a-makeSimple obj cons =- evalStateT (fromConstrM (do i:next <- get- put next- value <- lift (Map.lookup (Text.pack ("slot" ++ show i)) obj)- lift (readFromFay value))- cons)- [1..]---- | Make a record from a key-value: { "x": 1 } -> Foo { x = 1 }-makeRecord :: Data a => HashMap Text Value -> Constr -> [String] -> Maybe a-makeRecord obj cons fields =- evalStateT (fromConstrM (do key:next <- get- put next- value <- lift (Map.lookup (Text.pack key) obj)- lift (readFromFay value))- cons)- fields---- | Parse a double.-parseDouble :: Value -> Maybe Double-parseDouble value = do- number <- parseNumber value- case number of- I n -> return (fromIntegral n)- D n -> return n---- | Parse an int.-parseInt :: Value -> Maybe Int-parseInt value = do- number <- parseNumber value- case number of- I n -> return (fromIntegral n)- _ -> mzero---- | Parse a number.-parseNumber :: Value -> Maybe Number-parseNumber value =- case value of- Number n -> return n- _ -> mzero---- | Parse a bool.-parseBool :: Value -> Maybe Bool-parseBool value =- case value of- Bool n -> return n- _ -> mzero---- | Parse a string.-parseString :: Value -> Maybe String-parseString value =- case value of- String s -> return (Text.unpack s)- _ -> mzero---- | Parse a Text.-parseText :: Value -> Maybe Text-parseText value =- case value of- String s -> return s- _ -> mzero---- | Parse an array.-parseArray :: Data a => Value -> Maybe [a]-parseArray value =- case value of- Array xs -> mapM readFromFay (Vector.toList xs)- _ -> mzero
src/Language/Fay/FFI.hs view
@@ -2,9 +2,10 @@ {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE TypeSynonymInstances #-} +-- | The internal FFI module. Needs to be renamed to Fay.FFI at some point.+ module Language.Fay.FFI (Fay- ,Foreign ,Nullable (..) ,Defined (..) ,Ptr@@ -12,61 +13,18 @@ ,ffi) where -import Language.Fay.Types+import Fay.Types import Prelude (Bool, Char, Double, Int, Maybe, String, error) --- | Contains allowed foreign function types.-class Foreign a---- | Unit is OK.-instance Foreign ()---- | All numbers in JS are double.-instance Foreign Double---- | Some numbers in JS are int.-instance Foreign Int---- | Characters are OK.-instance Foreign Char---- | Bools are OK.-instance Foreign Bool---- | Lists → arrays are OK.-instance Foreign a => Foreign [a]---- | Tuples → arrays are OK.-instance (Foreign a, Foreign b) => Foreign (a,b)-instance (Foreign a, Foreign b, Foreign c) => Foreign (a,b,c)-instance (Foreign a, Foreign b, Foreign c, Foreign d) => Foreign (a,b,c,d)-instance (Foreign a, Foreign b, Foreign c, Foreign d,- Foreign e) => Foreign (a,b,c,d,e)-instance (Foreign a, Foreign b, Foreign c, Foreign d,- Foreign e, Foreign f) => Foreign (a,b,c,d,e,f)-instance (Foreign a, Foreign b, Foreign c, Foreign d,- Foreign e, Foreign f, Foreign g) => Foreign (a,b,c,d,e,f,g)---- | JS values are foreignable.-instance Foreign a => Foreign (Fay a)---- | Functions are foreignable.-instance (Foreign a,Foreign b) => Foreign (a -> b)---- | Maybes are pretty common.-instance Foreign a => Foreign (Maybe a)- -- | Values that may be null -- Nullable x decodes to x, Null decodes to null. data Nullable a = Nullable a | Null-instance Foreign a => Foreign (Nullable a) -- | Values that may be undefined -- Defined x encodes to x, Undefined decodes to undefined. -- An undefined property in a record will be removed when encoding. data Defined a = Defined a | Undefined-instance Foreign a => Foreign (Defined a) -- | Do not serialize the specified type. This is useful for, e.g. --
− src/Language/Fay/ModuleScope.hs
@@ -1,140 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}---- | Handles variable bindings on the module level and also keeps track of--- primitive operations that we want to treat specially.--module Language.Fay.ModuleScope- (ModuleScope- ,bindAsLocals- ,findTopLevelNames- ,resolveName- ,moduleLocals)- where--import Control.Arrow-import Control.Monad.Reader-import Control.Monad.Writer-import Data.Default-import Data.Map (Map)-import qualified Data.Map as M-import Language.Haskell.Exts hiding (name, binds)-import Prelude hiding (mod)---- | Maps names bound in the module to their real names--- The keys are unqualified for locals and imports,--- the values are always fully qualified--- Example contents:--- [ (UnQUal "main" , Qual "Main" "main")--- , (UnQual "take" , Qual "Prelude" "take")--- , ( Qual "M" "insertWith", Qual "Data.Map" "insertWith") ]-newtype ModuleScope = ModuleScope (Map QName QName)- deriving Show--instance Monoid ModuleScope where- mempty = ModuleScope M.empty- mappend (ModuleScope a) (ModuleScope b) = ModuleScope $ a `M.union` b--instance Default ModuleScope where- def = mempty---- | Find the path of a locally bound name--- Returns special values in the "Fay$" module for primOps-resolveName :: QName -> ModuleScope -> Maybe QName-resolveName q (ModuleScope binds) = case M.lookup q binds of -- lookup in the module environment.-- -- something pointing to prelude, is it a primop?- Just q'@(Qual (ModuleName "Prelude") n) -> case M.lookup n envPrimOpsMap of- Just x -> Just x -- A primop which looks like it's imported from prelude.- Nothing -> Just q' -- Regular prelude import, leave it as is.-- -- No matches in the current environment, so it may be a primop if it's unqualified.- -- If Nothing is returned from either of the branches it means that there is- -- no primop and nothing in env scope so GHC would have given an error.- Nothing -> case q of- UnQual n -> M.lookup n envPrimOpsMap- _ -> Nothing- j -> j -- Non-prelude import that was found in the env---- | Bind a list of names into the local scope--- Right now all bindings are made unqualified-bindAsLocals :: [QName] -> ModuleScope -> ModuleScope-bindAsLocals qs (ModuleScope binds) =- -- This needs to be changed to not use unqual to support qualified imports.- ModuleScope $ M.fromList (map (unqual &&& id) qs) `M.union` binds- where unqual (Qual _ n) = (UnQual n)- unqual u@UnQual{} = u- unqual Special{} = error "fay: ModuleScope.bindAsLocals: Special"---- | Find all names that are bound locally in this module, which excludes imports.-moduleLocals :: ModuleName -> ModuleScope -> [QName]-moduleLocals mod (ModuleScope binds) = filter isLocal . M.elems $ binds- where- isLocal (Qual m _) = mod == m- isLocal _ = False------------------------------------------------------------------------------------- Primitive Operations---- | The built-in operations that aren't actually compiled from--- anywhere, they come from runtime.js.------ They're in the names list so that they can be overriden by the user--- in e.g. let a * b = a - b in 1 * 2.------ So we resolve them to Fay$, i.e. the prefix used for the runtime--- support. $ is not allowed in Haskell module names, so there will be--- no conflicts if a user decicdes to use a module named Fay.------ So e.g. will compile to (*) Fay$$mult, which is in runtime.js.-envPrimOpsMap :: Map Name QName-envPrimOpsMap = M.fromList- [ (Symbol ">>", (Qual (ModuleName "Fay$") (Ident "then")))- , (Symbol ">>=", (Qual (ModuleName "Fay$") (Ident "bind")))- , (Ident "return", (Qual (ModuleName "Fay$") (Ident "return")))- , (Ident "force", (Qual (ModuleName "Fay$") (Ident "force")))- , (Ident "seq", (Qual (ModuleName "Fay$") (Ident "seq")))- , (Symbol "*", (Qual (ModuleName "Fay$") (Ident "mult")))- , (Symbol "+", (Qual (ModuleName "Fay$") (Ident "add")))- , (Symbol "-", (Qual (ModuleName "Fay$") (Ident "sub")))- , (Symbol "/", (Qual (ModuleName "Fay$") (Ident "div")))- , (Symbol "==", (Qual (ModuleName "Fay$") (Ident "eq")))- , (Symbol "/=", (Qual (ModuleName "Fay$") (Ident "neq")))- , (Symbol ">", (Qual (ModuleName "Fay$") (Ident "gt")))- , (Symbol "<", (Qual (ModuleName "Fay$") (Ident "lt")))- , (Symbol ">=", (Qual (ModuleName "Fay$") (Ident "gte")))- , (Symbol "<=", (Qual (ModuleName "Fay$") (Ident "lte")))- , (Symbol "&&", (Qual (ModuleName "Fay$") (Ident "and")))- , (Symbol "||", (Qual (ModuleName "Fay$") (Ident "or")))- ]------------------------------------------------------------------------------------- AST--type ModuleScopeSt = ReaderT ModuleName (Writer ModuleScope) ()---- | Get module level names from a haskell module AST.-findTopLevelNames :: ModuleName -> [Decl] -> ModuleScope-findTopLevelNames mod decls = snd . runWriter $ runReaderT (mapM_ d_decl decls) mod--bindName :: Name -> ModuleScopeSt-bindName k = ask >>= \mod -> tell (ModuleScope $ M.singleton (UnQual k) (Qual mod k))--d_decl :: Decl -> ModuleScopeSt-d_decl d = case d of- DataDecl _ _ _ _ _ dd _ -> mapM_ d_qualCon dd- PatBind _ (PVar n) _ _ _ -> bindName n- FunBind (Match _ n _ _ _ _ : _) -> bindName n- ClassDecl _ _ _ _ _ cds -> mapM_ d_classDecl cds- TypeSig _ ns _ -> mapM_ bindName ns- _ -> return ()--d_classDecl :: ClassDecl -> ModuleScopeSt-d_classDecl cd = case cd of- ClsDecl d -> d_decl d- _ -> return ()--d_qualCon :: QualConDecl -> ModuleScopeSt-d_qualCon (QualConDecl _ _ _ cd) = case cd of- ConDecl n _ -> bindName n- InfixConDecl _ n _ -> bindName n- RecDecl n ns -> bindName n >> mapM_ bindName (concatMap fst ns)
− src/Language/Fay/Prelude.hs
@@ -1,59 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}--module Language.Fay.Prelude- (Fay- ,Char- ,String- ,Integer- ,Double- ,Int- ,Bool(..)- ,Show- ,Read- ,Maybe(..)- ,Typeable(..)- ,Data(..)- ,Monad- ,Eq(..)- ,read- ,(>>)- ,(>>=)- ,(+)- ,(*)- ,(-)- ,(>)- ,(<)- ,(>=)- ,(<=)- ,(/)- ,(||)- ,(&&)- ,fail- ,return- ,force- ,module Language.Fay.Stdlib)- where--import Language.Fay.Stdlib-import Language.Fay.Types (Fay)-import Data.Data-import Prelude (Bool(..), Char, Double, Eq(..), Int, Integer, Maybe(..), Monad,- Ord, Read(..), Show(), String, read, (&&), (*), (+), (-),- (/), (/=), (<), (<=), (==), (>), (>=), (||))--(>>) :: Fay a -> Fay b -> Fay b-(>>) = error "Language.Fay.Prelude.(>>): Used (>>) outside JS."-infixl 1 >>--(>>=) :: Fay a -> (a -> Fay b) -> Fay b-(>>=) = error "Language.Fay.Prelude.(>>=): Used (>>=) outside JS."-infixl 1 >>=--fail :: String -> Fay a-fail = error "Language.Fay.Prelude.fail: Used fail outside JS."--return :: a -> Fay a-return = error "Language.Fay.Prelude.return: Used return outside JS."--force :: a -> Bool -> Fay a-force = error "Language.Fay.Prelude.force: Used force outside JS."
− src/Language/Fay/Print.hs
@@ -1,287 +0,0 @@-{-# OPTIONS -fno-warn-orphans #-}-{-# OPTIONS -fno-warn-unused-do-bind #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TypeSynonymInstances #-}---- | Simple code (non-pretty) printing.------ No clever printing is done here. If you want pretty printing, use a--- JS pretty printer. The output should be passed directly to a JS--- compressor, anyway.------ Special constructors and symbols in Haskell are encoded to--- JavaScript appropriately.--module Language.Fay.Print where--import Language.Fay.Types--import Control.Monad-import Control.Monad.State-import Data.Aeson.Encode-import qualified Data.ByteString.Lazy.UTF8 as UTF8-import Data.Default-import Data.List-import Data.String-import Language.Haskell.Exts.Syntax--import Prelude hiding (exp)------------------------------------------------------------------------------------- Printing--printJSString :: Printable a => a -> String-printJSString x = concat $ reverse $ psOutput $ execState (runPrinter (printJS x)) def--printJSPretty :: Printable a => a -> String-printJSPretty x = concat $ reverse $ psOutput $ execState (runPrinter (printJS x)) def { psPretty = True }---- | Print literals. These need some special encoding for--- JS-format literals. Could use the Text.JSON library.-instance Printable JsLit where- printJS typ = write $- let u8 = UTF8.toString . encode . UTF8.fromString- in case typ of- (JsChar char) -> u8 [char]- (JsStr str) -> u8 str- (JsInt int) -> show int- (JsFloating rat) -> show rat- (JsBool b) -> if b then "true" else "false"---- | Print (and properly encode to JS) a qualified name.-instance Printable QName where- printJS qname =- case qname of- Qual moduleName name -> moduleName +> "$" +> name- UnQual name -> printJS name- Special con -> printJS con---- | Print module name.-instance Printable ModuleName where- printJS (ModuleName "Fay$") =- write "Fay$"- printJS (ModuleName moduleName) = write $ go moduleName-- where go ('.':xs) = '$' : go xs- go (x:xs) = normalizeName [x] ++ go xs- go [] = []---- | Print special constructors (tuples, list, etc.)-instance Printable SpecialCon where- printJS specialCon =- printJS $ (Qual (ModuleName "Fay$") . Ident) $- case specialCon of- UnitCon -> "unit"- Cons -> "cons"- _ -> error $ "Special constructor not supported: " ++ show specialCon---- | Print (and properly encode) a name.-instance Printable Name where- printJS name = write $- case name of- Ident ident -> encodeName ident- Symbol sym -> encodeName sym---- | Print a list of statements.-instance Printable [JsStmt] where- printJS = mapM_ printJS---- | Print a single statement.-instance Printable JsStmt where- printJS (JsBlock stmts) =- "{ " +> stmts +> "}"- printJS (JsVar name expr) =- "var " +> name +> " = " +> expr +> ";" +> newline- printJS (JsUpdate name expr) =- name +> " = " +> expr +> ";" +> newline- printJS (JsSetProp name prop expr) =- name +> "." +> prop +> " = " +> expr +> ";" +> newline- printJS (JsSetPropExtern name prop expr) =- name +> "['" +> prop +> "'] = " +> expr +> ";" +> newline- printJS (JsIf exp thens elses) =- "if (" +> exp +> ") {" +> newline +>- indented (printJS thens) +>- "}" +>- (when (length elses > 0) $ " else {" +>- indented (printJS elses) +>- "}") +> newline- printJS (JsEarlyReturn exp) =- "return " +> exp +> ";" +> newline- printJS (JsThrow exp) = do- "throw " +> exp +> ";" +> newline- printJS (JsWhile cond stmts) =- "while (" +> cond +> ") {" +> newline +>- indented (printJS stmts) +>- "}" +> newline- printJS JsContinue =- printJS "continue;" +> newline- printJS (JsMappedVar _ name expr) =- "var " +> name +> " = " +> expr +> ";" +> newline---- | Print an expression.-instance Printable JsExp where- printJS (JsRawExp e) = write e- printJS (JsName name) = printJS name- printJS (JsThrowExp exp) =- "(function(){ throw (" +> exp +> "); })()"- printJS JsNull =- printJS "null"- printJS JsUndefined =- printJS "undefined"- printJS (JsLit lit) =- printJS lit- printJS (JsParen exp) =- "(" +> exp +> ")"- printJS (JsList exps) =- "[" +> intercalateM "," (map printJS exps) +> printJS "]"- printJS (JsNew name args) =- "new " +> (JsApp (JsName name) args)- printJS (JsIndex i exp) =- "(" +> exp +> ")[" +> show i +> "]"- printJS (JsEq exp1 exp2) =- exp1 +> " === " +> exp2- printJS (JsNeq exp1 exp2) =- exp1 +> " !== " +> exp2- printJS (JsGetProp exp prop) = exp +> "." +> prop- printJS (JsLookup exp1 exp2) =- exp1 +> "[" +> exp2 +> "]"- printJS (JsUpdateProp name prop expr) =- "(" +> name +> "." +> prop +> " = " +> expr +> ")"- printJS (JsInfix op x y) =- x +> " " +> op +> " " +> y- printJS (JsGetPropExtern exp prop) =- exp +> "[" +> (JsLit . JsStr) prop +> "]"- printJS (JsUpdatePropExtern name prop expr) =- "(" +> name +> "['" +> prop +> "'] = " +> expr +> ")"- printJS (JsTernaryIf cond conseq alt) =- cond +> " ? " +> conseq +> " : " +> alt- printJS (JsInstanceOf exp classname) =- exp +> " instanceof " +> classname- printJS (JsObj assoc) =- "{" +> (intercalateM "," (map cons assoc)) +> "}"- where cons (key,value) = "\"" +> key +> "\": " +> value- printJS (JsFun params stmts ret) =- "function("- +> (intercalateM "," (map printJS params))- +> "){" +> newline- +> indented (stmts +>- case ret of- Just ret' -> "return " +> ret' +> ";" +> newline- Nothing -> return ())- +> "}"- printJS (JsApp op args) =- (if isFunc op then JsParen op else op)- +> "("- +> (intercalateM "," (map printJS args))- +> ")"- where isFunc JsFun{..} = True; isFunc _ = False- printJS (JsNegApp args) =- "(-(" +> printJS args +> "))"---- | Print one of the kinds of names.-instance Printable JsName where- printJS name =- case name of- JsNameVar qname -> printJS qname- JsThis -> write "this"- JsThunk -> write "$"- JsForce -> write "_"- JsApply -> write "__"- JsParam i -> write ("$p" ++ show i)- JsTmp i -> write ("$tmp" ++ show i)- JsConstructor qname -> "$_" +> printJS qname- JsBuiltIn qname -> "Fay$$" +> printJS qname- JsParametrizedType -> write "type"--instance Printable String where- printJS = write--instance Printable (Printer ()) where- printJS = id------------------------------------------------------------------------------------- Name encoding---- Words reserved in haskell as well are not needed here:--- case, class, do, else, if, import, in, let-reservedWords :: [String]-reservedWords = [- "break", "catch", "const", "continue", "debugger", "delete", "enum", "export",- "extends", "finally", "for", "function", "global", "implements", "instanceof",- "interface", "new", "null", "package", "private", "protected", "public", "return",- "static", "super", "switch", "this", "throw", "try", "typeof", "undefined",- "var", "void", "while", "window", "with", "yield","true","false"]---- | Encode a Haskell name to JavaScript.-encodeName :: String -> String--- | This is a hack for names generated in the Haskell AST. Should be--- removed once it's no longer needed.-encodeName ('$':'g':'e':'n':name) = "$gen_" ++ normalizeName name-encodeName name- | name `elem` reservedWords = "$_" ++ normalizeName name- | otherwise = normalizeName name---- | Normalize the given name to JavaScript-valid names.-normalizeName :: [Char] -> [Char]-normalizeName name =- concatMap encodeChar name-- where- encodeChar c | c `elem` allowed = [c]- | otherwise = escapeChar c- allowed = ['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9'] ++ "_"- escapeChar c = "$" ++ charId c ++ "$"- charId c = show (fromEnum c)------------------------------------------------------------------------------------- Printing----- | Print the given printer indented.-indented :: Printer a -> Printer ()-indented p = do- PrintState{..} <- get- if psPretty- then do modify $ \s -> s { psIndentLevel = psIndentLevel + 1 }- p- modify $ \s -> s { psIndentLevel = psIndentLevel }- else p >> return ()---- | Output a newline.-newline :: Printer ()-newline = do- PrintState{..} <- get- when psPretty $ do- write "\n"- modify $ \s -> s { psNewline = True }---- | Write out a string, updating the current position information.-write :: String -> Printer ()-write x = do- PrintState{..} <- get- let out = if psNewline then replicate (2*psIndentLevel) ' ' ++ x else x- modify $ \s -> s { psOutput = out : psOutput- , psLine = psLine + additionalLines- , psColumn = if additionalLines > 0- then length (concat (take 1 (reverse srclines)))- else psColumn + length x- , psNewline = False- }- return (error "Nothing to return for writer string.")-- where srclines = lines x- additionalLines = length (filter (=='\n') x)---- | Intercalate monadic action.-intercalateM :: String -> [Printer a] -> Printer ()-intercalateM _ [] = return ()-intercalateM _ [x] = x >> return ()-intercalateM str (x:xs) = do- x- write str- intercalateM str xs---- | Concatenate two printables.-(+>) :: (Printable a, Printable b) => a -> b -> Printer ()-pa +> pb = printJS pa >> printJS pb
− src/Language/Fay/Stdlib.hs
@@ -1,735 +0,0 @@-{-# LANGUAGE NoImplicitPrelude #-}-module Language.Fay.Stdlib- (($)- ,($!)- ,(!!)- ,(++)- ,(.)- ,(=<<)- ,(**)- ,(^^)- ,(^)- ,Either(..)- ,Ordering(..)- ,abs- ,acos- ,acosh- ,all- ,and- ,any- ,asin- ,asinh- ,asTypeOf- ,atan- ,atanh- ,break- ,ceiling- ,compare- ,concat- ,concatMap- ,const- ,cos- ,cosh- ,curry- ,cycle- ,div- ,divMod- ,drop- ,dropWhile- ,either- ,elem- ,enumFrom- ,enumFromThen- ,enumFromThenTo- ,enumFromTo- ,error- ,even- ,exp- ,filter- ,find- ,flip- ,floor- ,foldl- ,foldl1- ,foldr- ,foldr1- ,forM_- ,fromInteger- ,fromIntegral- ,fromRational- ,fst- ,gcd- ,head- ,id- ,init- ,insertBy- ,intercalate- ,intersperse- ,iterate- ,last- ,lcm- ,length- ,lines- ,log- ,logBase- ,lookup- ,map- ,mapM_- ,max- ,maximum- ,maybe- ,min- ,minimum- ,mod- ,negate- ,not- ,notElem- ,nub- ,null- ,odd- ,or- ,otherwise- ,pi- ,pred- ,prependToAll- ,print- ,product- ,properFraction- ,putStrLn- ,quot- ,quotRem- ,recip- ,rem- ,repeat- ,replicate- ,reverse- ,round- ,scanl- ,scanl1- ,scanr- ,scanr1- ,seq- ,sequence- ,sequence_- ,show- ,signum- ,sin- ,sinh- ,snd- ,sort- ,sortBy- ,span- ,splitAt- ,sqrt- ,subtract- ,succ- ,sum- ,tail- ,take- ,takeWhile- ,tan- ,tanh- ,truncate- ,uncurry- ,undefined- ,unlines- ,until- ,unwords- ,unzip- ,unzip3- ,when- ,words- ,zip- ,zip3- ,zipWith- ,zipWith3)- where--import Language.Fay.FFI-import Prelude (Bool (..), Double, Eq (..), Fractional,- Fractional ((/)), Int, Integer, Maybe (..),- Monad (..), Num ((+), (-), (*)),- Ord ((>), (<)), Rational, Show, String, seq,- (&&), (||))--error :: String -> a-error str = case error' str of 0 -> error str ; _ -> error str--error' :: String -> Int-error' = ffi "(function() { throw %1 })()"--undefined :: a-undefined = error "Prelude.undefined"--show :: (Foreign a, Show a) => Automatic a -> String-show = ffi "JSON.stringify(%1)"--data Either a b = Left a | Right b--either :: (a -> c) -> (b -> c) -> Either a b -> c-either f _ (Left a) = f a-either _ g (Right b) = g b---- There is only Double in JS.-fromInteger :: a -> a-fromInteger x = x--fromRational :: a -> a-fromRational x = x--negate :: Num a => a -> a-negate x = (-x)--abs :: (Num a, Ord a) => a -> a-abs x = if x < 0 then negate x else x--signum :: (Num a, Ord a) => a -> a-signum x = if x > 0 then 1 else if x == 0 then 0 else -1--pi :: Double-pi = ffi "Math.PI"--exp :: Double -> Double-exp = ffi "Math.exp(%1)"--sqrt :: Double -> Double-sqrt = ffi "Math.sqrt(%1)"--log :: Double -> Double-log = ffi "Math.log(%1)"--(**) :: Double -> Double -> Double-(**) = unsafePow-infixr 8 **--(^^) :: Double -> Int -> Double-(^^) = unsafePow-infixr 8 ^^--unsafePow :: (Foreign a, Num a, Foreign b, Num b) => a -> b -> a-unsafePow = ffi "Math.pow(%1,%2)"--(^) :: Num a => a -> Int -> a-a ^ b | b < 0 = error "(^): negative exponent"- | b == 0 = 1- | even b = let x = a ^ (b `quot` 2) in x * x-a ^ b = a * a ^ (b - 1)-infixr 8 ^--logBase :: Double -> Double -> Double-logBase b x = log x / log b--sin :: Double -> Double-sin = ffi "Math.sin(%1)"--tan :: Double -> Double-tan = ffi "Math.tan(%1)"--cos :: Double -> Double-cos = ffi "Math.cos(%1)"--asin :: Double -> Double-asin = ffi "Math.asin(%1)"--atan :: Double -> Double-atan = ffi "Math.atan(%1)"--acos :: Double -> Double-acos = ffi "Math.acos(%1)"--sinh :: Double -> Double-sinh x = (exp x - exp (-x)) / 2--tanh :: Double -> Double-tanh x = let a = exp x ; b = exp (-x) in (a - b) / (a + b)--cosh :: Double -> Double-cosh x = (exp x + exp (-x)) / 2--asinh :: Double -> Double-asinh x = log (x + sqrt(x**2 + 1))--atanh :: Double -> Double-atanh x = log ((1 + x) / (1 - x)) / 2--acosh :: Double -> Double-acosh x = log (x + sqrt (x**2 - 1))--properFraction :: Double -> (Int, Double)-properFraction x = let a = truncate x in (a, x - fromIntegral a)--truncate :: Double -> Int-truncate x = if x < 0 then ceiling x else floor x--round :: Double -> Int-round = ffi "Math.round(%1)"--ceiling :: Double -> Int-ceiling = ffi "Math.ceil(%1)"--floor :: Double -> Int-floor = ffi "Math.floor(%1)"--subtract :: Num a => a -> a -> a-subtract = flip (-)--even :: Int -> Bool-even x = x `rem` 2 == 0--odd :: Int -> Bool-odd x = not (even x)--gcd :: Int -> Int -> Int-gcd a b = go (abs a) (abs b)- where go x 0 = x- go x y = go y (x `rem` y)--lcm :: Int -> Int -> Int-lcm _ 0 = 0-lcm 0 _ = 0-lcm a b = abs ((a `quot` (gcd a b)) * b)--curry :: ((a, b) -> c) -> a -> b -> c-curry f x y = f (x, y)--uncurry :: (a -> b -> c) -> (a, b) -> c-uncurry f p = case p of (x, y) -> f x y--snd :: (t, t1) -> t1-snd (_,x) = x--fst :: (t, t1) -> t-fst (x,_) = x--find :: (a -> Bool) -> [a] -> Maybe a-find p (x:xs) = if p x then Just x else find p xs-find _ [] = Nothing--filter :: (a -> Bool) -> [a] -> [a]-filter p (x:xs) = if p x then x : filter p xs else filter p xs-filter _ [] = []--not :: Bool -> Bool-not p = if p then False else True--null :: [t] -> Bool-null [] = True-null _ = False--map :: (a -> b) -> [a] -> [b]-map _ [] = []-map f (x:xs) = f x : map f xs--nub :: Eq a => [a] -> [a]-nub ls = nub' ls []--nub' :: Eq a => [a] -> [a] -> [a]-nub' [] _ = []-nub' (x:xs) ls =- if elem x ls- then nub' xs ls- else x : nub' xs (x : ls)--elem :: Eq a => a -> [a] -> Bool-elem x (y:ys) = x == y || elem x ys-elem _ [] = False--notElem :: Eq a => a -> [a] -> Bool-notElem x ys = not (elem x ys)--data Ordering = GT | LT | EQ--sort :: Ord a => [a] -> [a]-sort = sortBy compare--compare :: Ord a => a -> a -> Ordering-compare x y =- if x > y- then GT- else if x < y- then LT- else EQ---sortBy :: (t -> t -> Ordering) -> [t] -> [t]-sortBy cmp = foldr (insertBy cmp) []--insertBy :: (a -> a -> Ordering) -> a -> [a] -> [a]-insertBy _ x [] = [x]-insertBy cmp x ys =- case ys of- [] -> [x]- y:ys' ->- case cmp x y of- GT -> y : insertBy cmp x ys'- _ -> x : ys--when :: Monad m => Bool -> m a -> m ()-when p m = if p then m >> return () else return ()--succ :: Num a => a -> a-succ x = x + 1--pred :: Num a => a -> a-pred x = x - 1--enumFrom :: Num a => a -> [a]-enumFrom i = i : enumFrom (i + 1)--enumFromTo :: (Ord t, Num t) => t -> t -> [t]-enumFromTo i n =- if i > n then [] else i : enumFromTo (i + 1) n--enumFromBy :: (Num t) => t -> t -> [t]-enumFromBy fr by = fr : enumFromBy (fr + by) by--enumFromThen :: (Num t) => t -> t -> [t]-enumFromThen fr th = enumFromBy fr (th - fr)--enumFromByTo :: (Ord t, Num t) => t -> t -> t -> [t]-enumFromByTo fr by to = if by < 0 then neg fr else pos fr- where neg x = if x < to then [] else x : neg (x + by)- pos x = if x > to then [] else x : pos (x + by)--enumFromThenTo :: (Ord t, Num t) => t -> t -> t -> [t]-enumFromThenTo fr th to = enumFromByTo fr (th - fr) to--zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]-zipWith f (a:as) (b:bs) = f a b : zipWith f as bs-zipWith _ _ _ = []--zipWith3 :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]-zipWith3 f (a:as) (b:bs) (c:cs) = f a b c : zipWith3 f as bs cs-zipWith3 _ _ _ _ = []--zip :: [a] -> [b] -> [(a,b)]-zip (a:as) (b:bs) = (a,b) : zip as bs-zip _ _ = []--zip3 :: [a] -> [b] -> [c] -> [(a, b, c)]-zip3 (a:as) (b:bs) (c:cs) = (a,b,c) : zip3 as bs cs-zip3 _ _ _ = []--unzip :: [(a, b)] -> ([a], [b])-unzip ((x,y):ps) = case unzip ps of (xs,ys) -> (x:xs, y:ys)-unzip [] = ([], [])--unzip3 :: [(a, b, c)] -> ([a], [b], [c])-unzip3 ((x,y,z):ps) = case unzip3 ps of (xs,ys,zs) -> (x:xs, y:ys, z:zs)-unzip3 [] = ([], [], [])--lines :: String -> [String]-lines [] = []-lines s = case break isLineBreak s of (a, []) -> [a]- (a, _:cs) -> a : lines cs- where isLineBreak c = c == '\r' || c == '\n'--unlines :: [String] -> String-unlines = intercalate "\n"--words :: String -> [String]-words str = words' (dropWhile isSpace str)- where words' [] = []- words' s = case break isSpace s of (a,b) -> a : words b- isSpace c = c `elem` " \t\r\n\f\v"--unwords :: [String] -> String-unwords = intercalate " "--flip :: (t1 -> t2 -> t) -> t2 -> t1 -> t-flip f x y = f y x--maybe :: t -> (t1 -> t) -> Maybe t1 -> t-maybe m _ Nothing = m-maybe _ f (Just x) = f x--(.) :: (t1 -> t) -> (t2 -> t1) -> t2 -> t-(f . g) x = f (g x)-infixr 9 .--(++) :: [a] -> [a] -> [a]-x ++ y = conc x y-infixr 5 ++--($) :: (t1 -> t) -> t1 -> t-f $ x = f x-infixr 0 $---- | Append two lists.-conc :: [a] -> [a] -> [a]-conc (x:xs) ys = x : conc xs ys-conc [] ys = ys--concat :: [[a]] -> [a]-concat = foldr conc []--concatMap :: (a -> [b]) -> [a] -> [b]-concatMap f = foldr ((++) . f) []--foldr :: (t -> t1 -> t1) -> t1 -> [t] -> t1-foldr _ z [] = z-foldr f z (x:xs) = f x (foldr f z xs)--foldr1 :: (a -> a -> a) -> [a] -> a-foldr1 _ [x] = x-foldr1 f (x:xs) = f x (foldr1 f xs)-foldr1 _ [] = error "foldr1: empty list"--foldl :: (t1 -> t -> t1) -> t1 -> [t] -> t1-foldl _ z [] = z-foldl f z (x:xs) = foldl f (f z x) xs--foldl1 :: (a -> a -> a) -> [a] -> a-foldl1 f (x:xs) = foldl f x xs-foldl1 _ [] = error "foldl1: empty list"--and :: [Bool] -> Bool-and [] = True-and (x:xs) = x && and xs--or :: [Bool] -> Bool-or [] = False-or (x:xs) = x || or xs--any :: (a -> Bool) -> [a] -> Bool-any _ [] = False-any p (x:xs) = p x || any p xs--all :: (a -> Bool) -> [a] -> Bool-all _ [] = True-all p (x:xs) = p x && all p xs--maximum :: (Num a, Foreign a) => [a] -> a-maximum [] = error "maximum: empty list"-maximum xs = foldl1 max xs--minimum :: (Num a, Foreign a) => [a] -> a-minimum [] = error "minimum: empty list"-minimum xs = foldl1 min xs--product :: Num a => [a] -> a-product [] = error "product: empty list"-product xs = foldl (*) 1 xs--sum :: Num a => [a] -> a-sum [] = error "sum: empty list"-sum xs = foldl (+) 0 xs--scanl :: (a -> b -> a) -> a -> [b] -> [a]-scanl f z l = z : case l of [] -> []- (x:xs) -> scanl f (f z x) xs--scanl1 :: (a -> a -> a) -> [a] -> [a]-scanl1 _ [] = []-scanl1 f (x:xs) = scanl f x xs--scanr :: (a -> b -> b) -> b -> [a] -> [b]-scanr _ z [] = [z]-scanr f z (x:xs) = case scanr f z xs of (h:t) -> f x h : h : t- _ -> undefined--scanr1 :: (a -> a -> a) -> [a] -> [a]-scanr1 _ [] = []-scanr1 _ [x] = [x]-scanr1 f (x:xs) = case scanr1 f xs of (h:t) -> f x h : h : t- _ -> undefined--lookup :: Eq a1 => a1 -> [(a1, a)] -> Maybe a-lookup _key [] = Nothing-lookup key ((x,y):xys) =- if key == x- then Just y- else lookup key xys--intersperse :: a -> [a] -> [a]-intersperse _ [] = []-intersperse sep (x:xs) = x : prependToAll sep xs--prependToAll :: a -> [a] -> [a]-prependToAll _ [] = []-prependToAll sep (x:xs) = sep : x : prependToAll sep xs--intercalate :: [a] -> [[a]] -> [a]-intercalate xs xss = concat (intersperse xs xss)--forM_ :: Monad m => [t] -> (t -> m a) -> m ()-forM_ (x:xs) m = m x >> forM_ xs m-forM_ [] _ = return ()--mapM_ :: Monad m => (a -> m b) -> [a] -> m ()-mapM_ m (x:xs) = m x >> mapM_ m xs-mapM_ _ [] = return ()--const :: a -> b -> a-const a _ = a--length :: [a] -> Int-length xs = length' 0 xs--length' :: Int -> [a] -> Int-length' acc (_:xs) = length' (acc+1) xs-length' acc _ = acc--rem :: Int -> Int -> Int-rem x y = if y == 0 then error "Division by zero" else rem' x y-infixl 7 `rem`--rem' :: Int -> Int -> Int-rem' = ffi "%1 %% %2"--quot :: Int -> Int -> Int-quot x y = if y == 0 then error "Division by zero" else quot' x y-infixl 7 `quot`--quot' :: Int -> Int -> Int-quot' = ffi "~~(%1/%2)"--quotRem :: Int -> Int -> (Int, Int)-quotRem x y = (quot x y, rem x y)--div :: Int -> Int -> Int-div x y- | x > 0 && y < 0 = quot (x-1) y - 1- | x < 0 && y > 0 = quot (x+1) y - 1-div x y = quot x y-infixl 7 `div`--mod :: Int -> Int -> Int-mod x y- | x > 0 && y < 0 = rem (x-1) y + y + 1- | x < 0 && y > 0 = rem (x+1) y + y - 1-mod x y = rem x y-infixl 7 `mod`--divMod :: Int -> Int -> (Int, Int)-divMod x y- | x > 0 && y < 0 = case (x-1) `quotRem` y of (q,r) -> (q-1, r+y+1)- | x < 0 && y > 1 = case (x+1) `quotRem` y of (q,r) -> (q-1, r+y-1)-divMod x y = quotRem x y--min :: (Num a, Foreign a) => a -> a -> a-min = ffi "Math.min(%1,%2)"--max :: (Num a, Foreign a) => a -> a -> a-max = ffi "Math.max(%1,%2)"--recip :: Double -> Double-recip x = 1 / x--fromIntegral :: Int -> Double-fromIntegral = ffi "%1"--otherwise :: Bool-otherwise = True--reverse :: [a] -> [a]-reverse (x:xs) = reverse xs ++ [x]-reverse [] = []--(=<<) :: Monad m => (a -> m b) -> m a -> m b-f =<< x = x >>= f-infixl 1 =<<---- | Evaluate each action in the sequence from left to right,--- and collect the results.--- sequence :: [Fay a] -> Fay [a]-sequence :: (Monad m) => [m a] -> m [a]-sequence ms = foldr k (return []) ms- where- k m m' = do { x <- m; xs <- m'; return (x:xs) }--sequence_ :: Monad m => [m a] -> m ()-sequence_ [] = return ()-sequence_ (m:ms) = m >> sequence_ ms--id :: a -> a-id x = x--asTypeOf :: a -> a -> a-asTypeOf = const--until :: (a -> Bool) -> (a -> a) -> a -> a-until p f x = if p x then x else until p f (f x)--($!) :: (a -> b) -> a -> b-f $! x = x `seq` f x-infixr 0 $!--(!!) :: [a] -> Int -> a-a !! b = if b < 0 then error "(!!): negative index" else go a b- where go [] _ = error "(!!): index too large"- go (h:_) 0 = h- go (_:t) n = go t (n-1)-infixl 9 !!--head :: [a] -> a-head [] = error "head: empty list"-head (h:_) = h--tail :: [a] -> [a]-tail [] = error "tail: empty list"-tail (_:t) = t--init :: [a] -> [a]-init [] = error "init: empty list"-init [a] = [a]-init (h:t) = h : init t--last :: [a] -> a-last [] = error "last: empty list"-last [a] = a-last (_:t) = last t--iterate :: (a -> a) -> a -> [a]-iterate f x = x : iterate f (f x)--repeat :: a -> [a]-repeat x = x : repeat x--replicate :: Int -> a -> [a]-replicate 0 _ = []-replicate n x = if n < 0 then error "replicate: negative length"- else x : replicate (n-1) x--cycle :: [a] -> [a]-cycle [] = error "cycle: empty list"-cycle xs = xs' where xs' = xs ++ xs'--take :: Int -> [a] -> [a]-take 0 _ = []-take _ [] = []-take n (x:xs) = if n < 0 then error "take: negative length"- else x : take (n-1) xs--drop :: Int -> [a] -> [a]-drop 0 xs = xs-drop _ [] = []-drop n (_:xs) = if n < 0 then error "drop: negative length"- else drop (n-1) xs--splitAt :: Int -> [a] -> ([a], [a])-splitAt 0 xs = ([], xs)-splitAt _ [] = ([], [])-splitAt n (x:xs) = if n < 0 then error "splitAt: negative length"- else case splitAt (n-1) xs of (a,b) -> (x:a, b)--takeWhile :: (a -> Bool) -> [a] -> [a]-takeWhile _ [] = []-takeWhile p (x:xs) = if p x then x : takeWhile p xs else []--dropWhile :: (a -> Bool) -> [a] -> [a]-dropWhile _ [] = []-dropWhile p (x:xs) = if p x then dropWhile p xs else x:xs--span :: (a -> Bool) -> [a] -> ([a], [a])-span _ [] = ([], [])-span p (x:xs) = if p x then case span p xs of (a,b) -> (x:a, b) else ([], x:xs)--break :: (a -> Bool) -> [a] -> ([a], [a])-break p = span (not . p)--print :: (Foreign a) => Automatic a -> Fay ()-print = ffi "(function(x) { if (console && console.log) console.log(x) })(%1)"--putStrLn :: String -> Fay ()-putStrLn = ffi "(function(x) { if (console && console.log) console.log(x) })(%1)"
− src/Language/Fay/Types.hs
@@ -1,362 +0,0 @@-{-# OPTIONS -fno-warn-orphans #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings #-}---- | All Fay types and instances.--module Language.Fay.Types- (JsStmt(..)- ,JsExp(..)- ,JsLit(..)- ,JsName(..)- ,CompileError(..)- ,Compile(..)- ,CompilesTo(..)- ,Printable(..)- ,Fay- ,CompileReader(..)- ,CompileConfig(- configFlattenApps- ,configOptimize- ,configGClosure- ,configExportBuiltins- ,configPrettyPrint- ,configHtmlWrapper- ,configHtmlJSLibs- ,configLibrary- ,configWarn- ,configFilePath- ,configTypecheck- ,configWall- ,configPackageConf- )- ,configDirectoryIncludes- ,addConfigDirectoryInclude- ,addConfigDirectoryIncludes- ,configPackages- ,addConfigPackage- ,addConfigPackages- ,CompileState(..)- ,defaultCompileState- ,defaultCompileReader- ,faySourceDir- ,FundamentalType(..)- ,PrintState(..)- ,Printer(..)- ,Mapping(..)- ,SerializeContext(..))- where--import Control.Applicative-import Control.Monad.Error (Error, ErrorT, MonadError)-import Control.Monad.Identity (Identity)-import Control.Monad.State-import Control.Monad.RWS-import Data.Default-import Data.Map (Map)-import qualified Data.Map as M-import Data.Set (Set)-import qualified Data.Set as S-import Data.String-import Language.Haskell.Exts-import System.FilePath--import Language.Fay.ModuleScope (ModuleScope)-import Paths_fay------------------------------------------------------------------------------------- Compiler types---- | Configuration of the compiler.-data CompileConfig = CompileConfig- { configOptimize :: Bool- , configFlattenApps :: Bool- , configExportBuiltins :: Bool- , _configDirectoryIncludes :: [FilePath]- , configPrettyPrint :: Bool- , configHtmlWrapper :: Bool- , configHtmlJSLibs :: [FilePath]- , configLibrary :: Bool- , configWarn :: Bool- , configFilePath :: Maybe FilePath- , configTypecheck :: Bool- , configWall :: Bool- , configGClosure :: Bool- , configPackageConf :: Maybe FilePath- , _configPackages :: [String]- } deriving (Show)---- | Default configuration.-instance Default CompileConfig where- def =- addConfigPackage "fay-base" $- CompileConfig False False True [] False False [] False True Nothing True False False Nothing []---- Restrict these setters so elements aren't accidentally removed.--configDirectoryIncludes :: CompileConfig -> [FilePath]-configDirectoryIncludes = _configDirectoryIncludes--addConfigDirectoryInclude :: FilePath -> CompileConfig -> CompileConfig-addConfigDirectoryInclude fp cfg = cfg { _configDirectoryIncludes = fp : _configDirectoryIncludes cfg }--addConfigDirectoryIncludes :: [FilePath] -> CompileConfig -> CompileConfig-addConfigDirectoryIncludes fps cfg = foldl (flip addConfigDirectoryInclude) cfg fps--configPackages :: CompileConfig -> [String]-configPackages = _configPackages--addConfigPackage :: String -> CompileConfig -> CompileConfig-addConfigPackage pkg cfg = cfg { _configPackages = pkg : _configPackages cfg }--addConfigPackages :: [String] -> CompileConfig -> CompileConfig-addConfigPackages fps cfg = foldl (flip addConfigPackage) cfg fps---- | State of the compiler.-data CompileState = CompileState- { stateExports :: [QName]- , stateExportsCache :: Map ModuleName [QName] -- Collects exports from modules- , stateModuleName :: ModuleName- , stateFilePath :: FilePath- , stateRecordTypes :: [(QName,[QName])] -- Map types to constructors- , stateRecords :: [(QName,[QName])] -- Map constructors to fields- , stateFayToJs :: [JsStmt]- , stateJsToFay :: [JsStmt]- , stateImported :: [(ModuleName,FilePath)]- , stateNameDepth :: Integer- , stateLocalScope :: Set Name- , stateModuleScope :: ModuleScope-} deriving (Show)--data CompileReader = CompileReader- { readerConfig :: CompileConfig- } deriving (Show)--faySourceDir :: IO FilePath-faySourceDir = fmap (takeDirectory . takeDirectory . takeDirectory) (getDataFileName "src/Language/Fay/Stdlib.hs")---- | The default compiler reader value.-defaultCompileReader :: CompileConfig -> IO CompileReader-defaultCompileReader config = do- srcdir <- faySourceDir- return CompileReader- { readerConfig = addConfigDirectoryInclude srcdir config- }---- | The default compiler state.-defaultCompileState :: IO CompileState-defaultCompileState = do- types <- getDataFileName "src/Language/Fay/Types.hs"- return $ CompileState {- stateExports = []- , stateExportsCache = M.empty- , stateModuleName = ModuleName "Main"- , stateRecordTypes = []- , stateRecords = []- , stateFayToJs = []- , stateJsToFay = []- , stateImported = [("Language.Fay.Types",types)]- , stateNameDepth = 1- , stateFilePath = "<unknown>"- , stateLocalScope = S.empty- , stateModuleScope = def- }---- | Compile monad.-newtype Compile a = Compile- { unCompile :: RWST CompileReader- ()- CompileState (ErrorT CompileError IO)- a- }- deriving (MonadState CompileState- ,MonadError CompileError- ,MonadReader CompileReader- ,MonadIO- ,Monad- ,Functor- ,Applicative)---- | Just a convenience class to generalize the parsing/printing of--- various types of syntax.-class (Parseable from,Printable to) => CompilesTo from to | from -> to where- compileTo :: from -> Compile to--data Mapping = Mapping- { mappingName :: String- , mappingFrom :: SrcLoc- , mappingTo :: SrcLoc- } deriving (Show)--data PrintState = PrintState- { psPretty :: Bool- , psLine :: Int- , psColumn :: Int- , psMapping :: [Mapping]- , psIndentLevel :: Int- , psOutput :: [String]- , psNewline :: Bool- }--instance Default PrintState where- def = PrintState False 0 0 [] 0 [] False--newtype Printer a = Printer { runPrinter :: State PrintState a }- deriving (Monad,Functor,MonadState PrintState)---- | Print some value.-class Printable a where- printJS :: a -> Printer ()---- | Error type.-data CompileError- = ParseError SrcLoc String- | UnsupportedDeclaration Decl- | UnsupportedExportSpec ExportSpec- | UnsupportedMatchSyntax Match- | UnsupportedWhereInMatch Match- | UnsupportedExpression Exp- | UnsupportedLiteral Literal- | UnsupportedLetBinding Decl- | UnsupportedOperator QOp- | UnsupportedPattern Pat- | UnsupportedFieldPattern PatField- | UnsupportedRhs Rhs- | UnsupportedGuardedAlts GuardedAlts- | UnsupportedWhereInAlt Alt- | UnsupportedImport ImportDecl- | UnsupportedQualStmt QualStmt- | EmptyDoBlock- | UnsupportedModuleSyntax Module- | LetUnsupported- | InvalidDoBlock- | RecursiveDoUnsupported- | Couldn'tFindImport ModuleName [FilePath]- | FfiNeedsTypeSig Decl- | FfiFormatBadChars String- | FfiFormatNoSuchArg Int- | FfiFormatIncompleteArg- | FfiFormatInvalidJavaScript SrcLoc String String- | UnableResolveUnqualified Name- | UnableResolveQualified QName- | UnableResolveCachedImport ModuleName- deriving (Show)-instance Error CompileError---- | The JavaScript FFI interfacing monad.-newtype Fay a = Fay (Identity a)- deriving Monad------------------------------------------------------------------------------------- JS AST types---- | Statement type.-data JsStmt- = JsVar JsName JsExp- | JsMappedVar SrcLoc JsName JsExp- | JsIf JsExp [JsStmt] [JsStmt]- | JsEarlyReturn JsExp- | JsThrow JsExp- | JsWhile JsExp [JsStmt]- | JsUpdate JsName JsExp- | JsSetProp JsName JsName JsExp- | JsSetPropExtern JsName JsName JsExp- | JsContinue- | JsBlock [JsStmt]- deriving (Show,Eq)---- | Expression type.-data JsExp- = JsName JsName- | JsRawExp String- | JsFun [JsName] [JsStmt] (Maybe JsExp)- | JsLit JsLit- | JsApp JsExp [JsExp]- | JsNegApp JsExp- | JsTernaryIf JsExp JsExp JsExp- | JsNull- | JsParen JsExp- | JsGetProp JsExp JsName- | JsLookup JsExp JsExp- | JsUpdateProp JsExp JsName JsExp- | JsGetPropExtern JsExp String- | JsUpdatePropExtern JsExp JsName JsExp- | JsList [JsExp]- | JsNew JsName [JsExp]- | JsThrowExp JsExp- | JsInstanceOf JsExp JsName- | JsIndex Int JsExp- | JsEq JsExp JsExp- | JsNeq JsExp JsExp- | JsInfix String JsExp JsExp -- Used to optimize *, /, +, etc- | JsObj [(String,JsExp)]- | JsUndefined- deriving (Show,Eq)---- | A name of some kind.-data JsName- = JsNameVar QName- | JsThis- | JsParametrizedType- | JsThunk- | JsForce- | JsApply- | JsParam Integer- | JsTmp Integer- | JsConstructor QName- | JsBuiltIn Name- deriving (Eq,Show)---- | Literal value type.-data JsLit- = JsChar Char- | JsStr String- | JsInt Int- | JsFloating Double- | JsBool Bool- deriving (Show,Eq)---- | These are the data types that are serializable directly to native--- JS data types. Strings, floating points and arrays. The others are:--- actions in the JS monad, which are thunks that shouldn't be forced--- when serialized but wrapped up as JS zero-arg functions, and--- unknown types can't be converted but should at least be forced.-data FundamentalType- -- Recursive types.- = FunctionType [FundamentalType]- | JsType FundamentalType- | ListType FundamentalType- | TupleType [FundamentalType]- | UserDefined Name [FundamentalType]- | Defined FundamentalType- | Nullable FundamentalType- -- Simple types.- | DateType- | StringType- | DoubleType- | IntType- | BoolType- | PtrType- -- Automatically serialize this type.- | Automatic- -- Unknown.- | UnknownType- deriving (Show)---- | Helpful for some things.-instance IsString Name where- fromString = Ident---- | Helpful for some things.-instance IsString QName where- fromString = UnQual . Ident---- | Helpful for writing qualified symbols (Fay.*).-instance IsString ModuleName where- fromString = ModuleName--data SerializeContext = SerializeAnywhere | SerializeUserArg Int- deriving (Read,Show,Eq)
src/Main.hs view
@@ -5,8 +5,10 @@ module Main where -import Language.Fay-import Language.Fay.Compiler+import Fay+import Fay.Compiler+import Fay.Compiler.Config+import Fay.Compiler.Debug import qualified Control.Exception as E import Control.Monad@@ -23,22 +25,30 @@ -- | Options and help. data FayCompilerOptions = FayCompilerOptions- { optLibrary :: Bool- , optFlattenApps :: Bool- , optHTMLWrapper :: Bool- , optHTMLJSLibs :: [String]- , optInclude :: [String]- , optPackages :: [String]- , optWall :: Bool- , optNoGHC :: Bool- , optStdout :: Bool- , optVersion :: Bool- , optOutput :: Maybe String- , optPretty :: Bool- , optFiles :: [String]- , optOptimize :: Bool- , optGClosure :: Bool- , optPackageConf :: Maybe String+ { optLibrary :: Bool+ , optFlattenApps :: Bool+ , optHTMLWrapper :: Bool+ , optHTMLJSLibs :: [String]+ , optInclude :: [String]+ , optPackages :: [String]+ , optWall :: Bool+ , optNoGHC :: Bool+ , optStdout :: Bool+ , optVersion :: Bool+ , optOutput :: Maybe String+ , optPretty :: Bool+ , optFiles :: [String]+ , optOptimize :: Bool+ , optGClosure :: Bool+ , optPackageConf :: Maybe String+ , optNoRTS :: Bool+ , optNoStdlib :: Bool+ , optPrintRuntime :: Bool+ , optNaked :: Bool+ , optNoDispatcher :: Bool+ , optDispatcher :: Bool+ , optStdlibOnly :: Bool+ , optNoBuiltins :: Bool } -- | Main entry point.@@ -49,28 +59,37 @@ if optVersion opts then runCommandVersion else do- let config = addConfigDirectoryIncludes ("." : optInclude opts) $- addConfigPackages (optPackages opts) $ def- { configOptimize = optOptimize opts- , configFlattenApps = optFlattenApps opts- , configExportBuiltins = True -- optExportBuiltins opts- , configPrettyPrint = optPretty opts- , configLibrary = optLibrary opts- , configHtmlWrapper = optHTMLWrapper opts- , configHtmlJSLibs = optHTMLJSLibs opts- , configTypecheck = not $ optNoGHC opts- , configWall = optWall opts- , configGClosure = optGClosure opts- , configPackageConf = optPackageConf opts <|> packageConf- }- void $ incompatible htmlAndStdout opts "Html wrapping and stdout are incompatible"- case optFiles opts of- ["-"] -> hGetContents stdin >>= printCompile config compileModule- [] -> runInteractive- files -> forM_ files $ \file -> do- if optStdout opts- then compileFromTo config file Nothing- else compileFromTo config file (Just (outPutFile opts file))+ if optPrintRuntime opts+ then getRuntime >>= readFile >>= putStr+ else do+ let config = addConfigDirectoryIncludePaths ("." : optInclude opts) $+ addConfigPackages (optPackages opts) $ def+ { configOptimize = optOptimize opts+ , configFlattenApps = optFlattenApps opts+ , configExportBuiltins = not (optNoBuiltins opts)+ , configPrettyPrint = optPretty opts+ , configLibrary = optLibrary opts+ , configHtmlWrapper = optHTMLWrapper opts+ , configHtmlJSLibs = optHTMLJSLibs opts+ , configTypecheck = not $ optNoGHC opts+ , configWall = optWall opts+ , configGClosure = optGClosure opts+ , configPackageConf = optPackageConf opts <|> packageConf+ , configExportRuntime = not (optNoRTS opts)+ , configNaked = optNaked opts+ , configExportStdlib = not (optNoStdlib opts)+ , configDispatchers = not (optNoDispatcher opts)+ , configDispatcherOnly = optDispatcher opts+ , configExportStdlibOnly = optStdlibOnly opts+ }+ void $ incompatible htmlAndStdout opts "Html wrapping and stdout are incompatible"+ case optFiles opts of+ ["-"] -> hGetContents stdin >>= printCompile config (compileModule True)+ [] -> runInteractive+ files -> forM_ files $ \file -> do+ if optStdout opts+ then compileFromTo config file Nothing+ else compileFromTo config file (Just (outPutFile opts file)) where parser = info (helper <*> options) (fullDesc <> header helpTxt)@@ -100,6 +119,14 @@ <*> switch (long "optimize" <> short 'O' <> help "Apply optimizations to generated code") <*> switch (long "closure" <> help "Provide help with Google Closure") <*> optional (strOption (long "package-conf" <> help "Specify the Cabal package config file"))+ <*> switch (long "no-rts" <> short 'r' <> help "Don't export the RTS")+ <*> switch (long "no-stdlib" <> help "Don't generate code for the Prelude/FFI")+ <*> switch (long "print-runtime" <> help "Print the runtime JS source to stdout")+ <*> switch (long "naked" <> help "Print all declarations naked at the top-level (unwrapped)")+ <*> switch (long "no-dispatcher" <> help "Don't output a type serialization dispatcher")+ <*> switch (long "dispatcher" <> help "Only output the type serialization dispatchers")+ <*> switch (long "stdlib" <> help "Only output the stdlib")+ <*> switch (long "no-builtins" <> help "Don't export no-builtins") where strsOption m = nullOption (m <> reader (Right . wordsBy (== ',')) <> value [])@@ -148,9 +175,9 @@ outputStrLn ("can't parse input as expression: " ++ show err) result' <- liftIO $ compileViaStr "<interactive>" config (compileDecl True) input case result' of- Right (PrintState{..},_) -> outputStr (concat (reverse psOutput))+ Right (PrintState{..},_,_) -> outputStr (concat (reverse psOutput)) Left err' -> outputStrLn ("can't parse input as declaration: " ++ show err')- Right (PrintState{..},_) -> outputStr (concat (reverse psOutput))+ Right (PrintState{..},_,_) -> outputStr (concat (reverse psOutput)) loop config = def { configPrettyPrint = True }
src/Test/Api.hs view
@@ -3,7 +3,8 @@ module Test.Api (tests) where -import Language.Fay+import Fay+import Fay.Compiler.Config import Data.Default import Data.Maybe@@ -12,7 +13,7 @@ import Test.Framework import Test.Framework.Providers.HUnit import Test.Framework.TH-import Test.HUnit (Assertion, assertBool, assertEqual)+import Test.HUnit (Assertion, assertBool, assertEqual, assertFailure) import Test.Util tests :: Test@@ -61,9 +62,15 @@ ] (stateRecordTypes r) +case_typecheckCPP :: Assertion+case_typecheckCPP = do+ whatAGreatFramework <- fmap (lookup "HASKELL_PACKAGE_SANDBOX") getEnvironment+ res <- compileFile defConf { configPackageConf = whatAGreatFramework, configTypecheck = True, configFilePath = Just "tests/Api/CPPTypecheck.hs" } "tests/Api/CPPTypecheck.hs"+ either (assertFailure . show) (const $ return ()) res+ fp :: FilePath fp = "tests/RecordImport_Import.hs" defConf :: CompileConfig-defConf = addConfigDirectoryInclude "tests/"+defConf = addConfigDirectoryIncludePaths ["tests/"] $ def { configTypecheck = False }
src/Test/Convert.hs view
@@ -10,7 +10,7 @@ import Data.Data import Data.Ratio import Data.Text (Text, pack)-import Language.Fay.Convert+import Fay.Convert import Test.Framework import Test.Framework.Providers.HUnit import Test.HUnit (assertEqual)
src/Tests.hs view
@@ -7,11 +7,13 @@ module Main where +import Fay+import Fay.Compiler.Config+ import Control.Applicative import Data.Default import Data.List import Data.Maybe-import Language.Fay import System.Directory import System.Environment import System.FilePath@@ -49,7 +51,7 @@ let root = (reverse . drop 1 . dropWhile (/='.') . reverse) file out = toJsName file config =- addConfigDirectoryInclude "tests/" $+ addConfigDirectoryIncludePaths ["tests/"] $ def { configOptimize = opt , configTypecheck = False , configPackageConf = packageConf
− src/Text/Blaze/Extra.hs
@@ -1,34 +0,0 @@-{-# OPTIONS -fno-warn-orphans #-}-{-# LANGUAGE OverloadedStrings #-}-{-# OPTIONS -fno-warn-name-shadowing -fno-warn-unused-do-bind #-}--module Text.Blaze.Extra where--import Control.Monad-import Data.Monoid-import Text.Blaze.Html5 as H hiding (map)-import Text.Blaze.Html5.Attributes as A-import Text.Blaze.Internal (Attributable)--(!.) :: (Attributable h) => h -> AttributeValue -> h-elem !. className = elem ! class_ className--(!#) :: (Attributable h) => h -> AttributeValue -> h-elem !# idName = elem ! A.id idName--linesToHtml :: String -> Html-linesToHtml str = forM_ (lines str) $ \line -> do toHtml line; br--htmlIntercalate :: Html -> [Html] -> Html-htmlIntercalate _ [x] = x-htmlIntercalate sep (x:xs) = do x; sep; htmlIntercalate sep xs-htmlIntercalate _ [] = mempty--htmlCommasAnd :: [Html] -> Html-htmlCommasAnd [x] = x-htmlCommasAnd [x,y] = do x; " and "; y-htmlCommasAnd (x:xs) = do x; ", "; htmlCommasAnd xs-htmlCommasAnd [] = mempty--htmlCommas :: [Html] -> Html-htmlCommas = htmlIntercalate ", "
+ tests/Api/CPPTypecheck.hs view
@@ -0,0 +1,13 @@+{-# LANGUAGE CPP #-}++module CPPTypecheck where++#ifdef FAY+import FFI+import Prelude+#endif++data R = R { time :: String }++main :: Fay ()+main = print $ R "x"
tests/List.hs view
@@ -1,4 +1,4 @@-import Language.Fay.FFI+import FFI import Prelude main = putStrLn (showList (take 5 (let ns = 1 : map' (\x -> x + 1) ns in ns)))
tests/List2.hs view
@@ -1,4 +1,4 @@-import Language.Fay.FFI+import FFI import Prelude main = putStrLn (showList (take 5 (let ns = 1 : map' (foo 123) ns in ns)))
tests/RecDecl.hs view
@@ -1,4 +1,4 @@-import Language.Fay.FFI+import FFI import Prelude data R = R { i :: Double, c :: Char }
tests/mutableReference.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE EmptyDataDecls #-} -import Language.Fay.FFI+import FFI import Prelude main :: Fay ()
tests/patternGuards.hs view
@@ -3,7 +3,7 @@ -- | As pattern matches import Prelude-import Language.Fay.FFI+import FFI isPositive :: Double -> Bool isPositive x | x > 0 = True
+ tests/serialization view
@@ -0,0 +1,17 @@+{ instance: 'Parametric',+ slot1: { instance: 'ConcreteRecord', concreteField: 123 } }+{ instance: 'Parametric',+ slot1: { instance: 'ConcreteRecord', concreteField: 123 } }+{ instance: 'Parametric',+ slot1: { forced: false, value: [Function] } }+{ instance: 'Just',+ slot1: { instance: 'ConcreteRecord', concreteField: 42 } }+{ instance: 'Just',+ slot1: { instance: 'ConcreteRecord', concreteField: 42 } }+{ instance: 'Just',+ slot1: { forced: false, value: [Function] } }+{ forced: false, value: [Function] }+{ instance: 'Just',+ slot1: { forced: false, value: [Function] } }+{ instance: 'Just',+ slot1: { instance: 'ConcreteRecord', concreteField: 42 } }
+ tests/serialization.hs view
@@ -0,0 +1,42 @@+import Prelude+import FFI++data Parametric a = Parametric a+data ConcreteRecord = ConcreteRecord { concreteField :: Double }+main = do+ printParametricButConcreteType (Parametric (ConcreteRecord 123))+ printParametricButAutomaticType (Parametric (ConcreteRecord 123))+ printParametricType (Parametric (ConcreteRecord 123))+ printMaybeConcrete (Just (ConcreteRecord 42))+ printMaybeAutomatic (Just (ConcreteRecord 42))+ printMaybe (Just (ConcreteRecord 42))+ printUnknown (error "do not want")+ printUnknownField (Just (error "do not want"))+ printAutomatic (Just (ConcreteRecord 42))++printParametricButConcreteType :: Parametric ConcreteRecord -> Fay ()+printParametricButConcreteType = ffi "console.log(%1)"++printParametricButAutomaticType :: Parametric (Automatic a) -> Fay ()+printParametricButAutomaticType = ffi "console.log(%1)"++printParametricType :: Parametric a -> Fay ()+printParametricType = ffi "console.log(%1)"++printMaybeConcrete :: Maybe ConcreteRecord -> Fay ()+printMaybeConcrete = ffi "console.log(%1)"++printMaybeAutomatic :: Maybe (Automatic a) -> Fay ()+printMaybeAutomatic = ffi "console.log(%1)"++printMaybe :: Maybe a -> Fay ()+printMaybe = ffi "console.log(%1)"++printUnknown :: a -> Fay ()+printUnknown = ffi "console.log(%1)"++printUnknownField :: Maybe a -> Fay ()+printUnknownField = ffi "console.log(%1)"++printAutomatic :: Automatic a -> Fay ()+printAutomatic = ffi "console.log(%1)"
tests/tailRecursion view
@@ -1,1 +1,1 @@-5000050000+500500
tests/tailRecursion.hs view
@@ -2,8 +2,7 @@ import Prelude main = do- print (sumTo 100000 0 :: Double)+ print (sumTo 1000 0 :: Double) sumTo 0 acc = acc sumTo n acc = sumTo (n - 1) (acc + n)-