infernu-0.0.0.0: src/Infernu/Builtins/String.hs
{-# LANGUAGE TupleSections #-}
module Infernu.Builtins.String
(stringRowType)
where
import Control.Monad (foldM, forM)
import Infernu.Types
import Infernu.InferState
import Infernu.Lib (safeLookup)
func :: Type -> Type -> Type -> Type
func this x y = Fix $ TFunc [this, x] y
string :: Type
string = Fix $ TBody TString
number :: Type
number = Fix $ TBody TNumber
ts :: t -> TScheme t
ts t = TScheme [] $ qualEmpty t
stringProps :: [(String, TypeScheme)]
stringProps =
[ ("length", ts number)
, ("charAt", ts $ func string number string)
, ("charCodeAt", ts $ func string number number)
, ("concat", ts $ func string string string) -- TODO: concat really accepts a variable number of arguments
, ("indexOf", ts $ func string string number) -- TODO: optional parameter
, ("lastIndexOf", ts $ func string string number) -- TODO: optional parameter
, ("localeCompare", ts $ func string string number) -- TODO: optional parameters
-- To support 'match' we need to allow different result types, different for global and non-global
-- regexes. One possibility is to define two regex types RegexSingle and RegexGlobal and use
-- associated types:
-- class Regex r where
-- type R r = r
-- type M RegexLocal = -- match result type for RegexLocal
-- type M RegexGlobal = [String]
--
-- , ("match", ts $ func string regex
]
-- TODO: when inserting builtin types, do fresh renaming of scheme qvars
stringRowType :: Infer (TRowList Type)
stringRowType = foldM addProp (TRowEnd Nothing) $ stringProps
where addProp rowlist (name, propTS) =
do allocNames <- forM (schemeVars propTS) $ \tvName -> (fresh >>= return . (tvName,))
let ts' = mapVarNames (safeLookup allocNames) propTS
return $ TRowProp name ts' rowlist