Infer types in record literals.

This also changes the behaviour for array literals so that the inferred type of
the first item is used as the default for the rest. This satisfies all the
cgtests except for a test in cgtest59 which does "a IS [3, 4 (type)]:", which
I've never seen in a real program, and would require a bit more complication to
handle.
This commit is contained in:
Adam Sampson 2008-04-07 00:05:15 +00:00
parent 6d31c79234
commit d0072fc2ee

View File

@ -860,7 +860,8 @@ inferTypes = applyExplicitM9 doExpression doDimension doSubscript
A.ArrayLiteral m aes ->
do (t, A.ArrayElemArray aes') <-
doArrayElem wantT (A.ArrayElemArray aes)
return (t, A.ArrayLiteral m aes')
lr' <- buildTable t aes'
return (t, lr')
_ ->
do lr' <- descend lr
(defT, isT) <-
@ -876,6 +877,8 @@ inferTypes = applyExplicitM9 doExpression doDimension doSubscript
(_, True) -> return (wantT, lr')
(_, False) -> diePC m $ formatCode "Literal of default type % is not valid for type %" defT wantT
where
m = findMeta lr
doArrayElem :: A.Type -> A.ArrayElem -> PassM (A.Type, A.ArrayElem)
-- A table: this could be an array or a record.
doArrayElem wantT (A.ArrayElemArray aes)
@ -883,26 +886,34 @@ inferTypes = applyExplicitM9 doExpression doDimension doSubscript
case underT of
A.Array _ _ ->
do subT <- trivialSubscriptType m underT
taes <- mapM (doArrayElem subT) aes
return (applyDimension (makeDimension m $ length aes)
wantT,
A.ArrayElemArray (map snd taes))
-- FIXME: Implement this
A.Record n -> dieP m "FIXME: implement record constants"
(elemT, aes') <- doElems subT aes
let dims = [makeDimension m (length aes)]
return (addDimensions dims elemT,
A.ArrayElemArray aes')
A.Record _ ->
do nts <- recordFields m underT
aes <- sequence [doArrayElem t ae >>* snd
| ((_, t), ae) <- zip nts aes]
return (wantT, A.ArrayElemArray aes)
-- If we don't know, assume it's an array.
A.Infer ->
do taes <- mapM (doArrayElem A.Infer) aes
elemT <- case taes of
-- Empty list -- can't tell what
-- the element type is.
[] -> dieP m "Cannot infer type of empty array"
-- Else use the type of the first
-- element.
((t, _):_) -> return t
let dims = [makeDimension m (length taes)]
do (elemT, aes') <- doElems A.Infer aes
when (elemT == A.Infer) $
dieP m "Cannot infer type of (empty?) array"
let dims = [makeDimension m (length aes)]
return (addDimensions dims elemT,
A.ArrayElemArray (map snd taes))
A.ArrayElemArray aes')
_ -> diePC m $ formatCode "Table literal is not valid for type %" wantT
where
-- | When walking along an array literal, use the type of the
-- first element as the default for the rest.
doElems :: A.Type -> [A.ArrayElem] -> PassM (A.Type, [A.ArrayElem])
doElems t [] = return (t, [])
doElems t (ae:aes)
= do (t', ae') <- doArrayElem t ae
aes' <- sequence [doArrayElem t' ae >>* snd
| ae <- aes]
return (t', ae':aes')
-- An expression: descend into it with the right context.
doArrayElem wantT (A.ArrayElemExpr e)
= do e' <- inTypeContext (Just wantT) $ doExpression descend e
@ -910,7 +921,39 @@ inferTypes = applyExplicitM9 doExpression doDimension doSubscript
checkType (findMeta e') wantT t
return (t, A.ArrayElemExpr e')
m = findMeta lr
-- | Turn a raw table literal into the appropriate combination of
-- arrays and records.
buildTable :: A.Type -> [A.ArrayElem] -> PassM A.LiteralRepr
buildTable t aes
= do underT <- underlyingType m t
case underT of
A.Array _ _ ->
do elemT <- trivialSubscriptType m t
aes' <- mapM (buildElem elemT) aes
return $ A.ArrayLiteral m aes'
A.Record _ ->
do nts <- recordFields m underT
aes' <- sequence [buildExpr elemT ae
| ((_, elemT), ae) <- zip nts aes]
return $ A.RecordLiteral m aes'
where
buildExpr :: A.Type -> A.ArrayElem -> PassM A.Expression
buildExpr t (A.ArrayElemArray aes)
= do lr <- buildTable t aes
return $ A.Literal m t lr
buildExpr _ (A.ArrayElemExpr e) = return e
buildElem :: A.Type -> A.ArrayElem -> PassM A.ArrayElem
buildElem t ae
= do underT <- underlyingType m t
case (underT, ae) of
(A.Array _ _, A.ArrayElemArray aes) ->
do A.ArrayLiteral _ aes' <- buildTable t aes
return $ A.ArrayElemArray aes'
(A.Record _, A.ArrayElemArray _) ->
do e <- buildExpr t ae
return $ A.ArrayElemExpr e
(_, A.ArrayElemExpr _) -> return ae
--}}}
--{{{ checkTypes