{-# 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