packages feed

hssqlppp-0.2.0: Database/HsSqlPpp/AstInternals/TypeChecking/Misc.ag

{-
Copyright 2009 Jake Wheat

Contains bit and pieces of type checking which don't fit anywhere else

================================================================================

= type names

Types with type modifiers (called PrecTypeName here, to be changed),
are not supported at the moment.

-}

ATTR TypeName [||namedType : Type]

SEM TypeName
     | SimpleTypeName ArrayTypeName SetOfTypeName PrecTypeName
         lhs.namedType = tpeToT @loc.tpe
         lhs.annotatedTree = updateAnnotation
                               ((map TypeErrorA $ getErrors @loc.tpe) ++)
                               @loc.backTree


SEM TypeName
     | SimpleTypeName
        loc.tpe = catLookupType @lhs.cat $ canonicalizeTypeName @tn
        loc.backTree = SimpleTypeName @ann @tn
     | ArrayTypeName
        loc.tpe = dependsOnRTpe [@typ.namedType] $ Right $ ArrayType @typ.namedType
        loc.backTree = ArrayTypeName @ann @typ.annotatedTree
     | SetOfTypeName
        loc.tpe = dependsOnRTpe [@typ.namedType] $ Right $ SetOfType @typ.namedType
        loc.backTree = SetOfTypeName @ann @typ.annotatedTree
     | PrecTypeName
        loc.tpe = catLookupType @lhs.cat $ canonicalizeTypeName @tn
        loc.backTree = PrecTypeName @ann @tn @prec


{-
================================================================================

= generic node types

-}

--expression list and list list - just collect up the types

ATTR ExpressionList [||typeList : {[Type]}]

SEM ExpressionList
    | Cons lhs.typeList = getTypeAnnotation @hd.annotatedTree : @tl.typeList
    | Nil lhs.typeList = []


ATTR ExpressionListList  [||typeListList : {[[Type]]}]

SEM ExpressionListList
    | Cons lhs.typeListList = @hd.typeList : @tl.typeListList
    | Nil lhs.typeListList = []


-- stringlist: collect the strings
ATTR StringList [||strings : {[String]}]

SEM StringList
  | Cons lhs.strings = @hd : @tl.strings
  | Nil lhs.strings = []

-- maybe bool expression: if present, then check its type is bool

SEM MaybeBoolExpression
    | Just
        lhs.annotatedTree =
          if getTypeAnnotation @just.annotatedTree `notElem` [typeBool, TypeCheckFailed]
            then Just $ updateAnnotation ((TypeErrorA ExpressionMustBeBool) :)
                          @just.annotatedTree
            else Just $ @just.annotatedTree


{
{-
================================================================================

= couple of small utils

I think this should be alright, an identifier referenced in an
expression can only have zero or one dot in it.
-}

splitIdentifier :: String -> (String,String)
splitIdentifier s = let (a,b) = span (/= '.') s
                    in if b == ""
                         then ("", a)
                         else (a,tail b)

{-
helper to make adding annotations a bit easier
-}

annTypesAndErrors :: Data a => a -> Type -> [TypeError]
                  -> Maybe [AnnotationElement] -> a
annTypesAndErrors item nt errs add =
    updateAnnotation modifier item
    where
      modifier = (([TypeAnnotation nt] ++ fromMaybe [] add ++
       map TypeErrorA errs) ++)

{-
================================================================================

proper dodgy:
1st pass is to add inferred types to the tree. This is done only for
expressions in a funcall argument list atm. Then we pull out the
placeholders after they've had this information added. Only the
placeholders in funcall argument lists will have their type inferred
in this way, to be expanded. Insert also does this currently, but in Dml.ag

This should probably be done during the typechecking phase instead,
but probably needs a proper type inferencing algorithm to be used, is
done like this for development expediency.

-}
getPlaceholders :: Data a => a -> [Expression]
getPlaceholders st =
    filter isPlaceholder $ everything (++) (mkQ [] ga) (setInferredTypes st)
    where
      ga :: Expression -> [Expression]
      ga s = [s]
      isPlaceholder e = case e of
                          PositionalArg _ _ -> True
                          Placeholder _ -> True
                          _ -> False

getPlaceholderTypes :: Data a => a -> [Type]
getPlaceholderTypes ex =
    map (getInferredType . getAnnotation) $ getPlaceholders ex
    where
      getInferredType (InferredType t:_) = t
      getInferredType (_:as) = getInferredType as
      getInferredType [] = TypeCheckFailed


setInferredTypes :: Data a => a -> a
setInferredTypes =
      doExprs {-. doSts-}
     where
       doExprs =
         transformBi (\x ->
           case x of
             FunCall an op exprs
                 -> FunCall an op (addInferredTypes an exprs)
             x1 -> x1)
       {-doSts =
         transformBi (\x ->
           case x of
             Insert ann table targetCols insData returning
                 -> Insert ann table targetCols insData returning
             x1 -> x1)-}
       addInferredTypes an exprs =
           let args1 = fmap (\(_,a,_,_) -> a) $ fp an
               args = fromMaybe [] args1
               fargs = args ++ repeat TypeCheckFailed
           in flip map (zip exprs fargs)
                  (\(ex, ty) -> updateAnnotation (++ [InferredType ty]) ex)
           where
             fp (FunctionPrototypeA f:_) = Just f
             fp (_:ls) = fp ls
             fp [] = Nothing

}