Pick the best type available for operators and array literals.

This is rather more expensive than the approach it was using, but it
does the right thing for things like "3 + 4(MYINT)" and "[3, 4(MYINT)]",
and the code's actually simpler.
This commit is contained in:
Adam Sampson 2008-04-07 20:14:00 +00:00
parent 3326c56a54
commit cc907a1339

View File

@ -172,6 +172,23 @@ checkExpressionInt e = checkExpressionType A.Int e
checkExpressionBool :: Check A.Expression checkExpressionBool :: Check A.Expression
checkExpressionBool e = checkExpressionType A.Bool e checkExpressionBool e = checkExpressionType A.Bool e
-- | Pick the more specific of a pair of types.
betterType :: A.Type -> A.Type -> A.Type
betterType t1 t2
= case betterType' t1 t2 of
Left () -> t1
Right () -> t2
where
betterType' :: A.Type -> A.Type -> Either () ()
betterType' A.Infer t = Right ()
betterType' t A.Infer = Left ()
betterType' t@(A.UserDataType _) _ = Left ()
betterType' _ t@(A.UserDataType _) = Right ()
betterType' t1@(A.Array ds1 et1) t2@(A.Array ds2 et2)
| length ds1 == length ds2 = betterType' et1 et2
| length ds1 < length ds2 = Left ()
betterType' t _ = Left ()
--}}} --}}}
--{{{ more complex checks --{{{ more complex checks
@ -624,25 +641,21 @@ inferTypes = applyExplicitM9 doExpression doDimension doSubscript
-- Expressions that aren't literals, but that modify the type -- Expressions that aren't literals, but that modify the type
-- context. -- context.
A.Dyadic m op le re -> A.Dyadic m op le re ->
case classifyOp op of let -- Both types are the same.
-- No info about the LHS; infer the RHS type from the LHS. bothSame
ComparisonOp -> = do lt <- inferTypes le >>= typeOfExpression
do le' <- noTypeContext $ inferTypes le rt <- inferTypes re >>= typeOfExpression
t <- typeOfExpression le' inTypeContext (Just $ betterType lt rt) $
re' <- inTypeContext (Just t) $ inferTypes re descend outer
return $ A.Dyadic m op le' re'
-- The RHS type is always A.Int. -- The RHS type is always A.Int.
ShiftOp -> intOnRight
do le' <- inferTypes le = do le' <- inferTypes le
re' <- inTypeContext (Just A.Int) $ inferTypes re re' <- inTypeContext (Just A.Int) $ inferTypes re
return $ A.Dyadic m op le' re' return $ A.Dyadic m op le' re'
-- Otherwise infer the LHS from the current context, in case classifyOp op of
-- then the RHS from that. ComparisonOp -> noTypeContext $ bothSame
_ -> ShiftOp -> intOnRight
do le' <- inferTypes le _ -> bothSame
t <- typeOfExpression le'
re' <- inTypeContext (Just t) $ inferTypes re
return $ A.Dyadic m op le' re'
A.SizeExpr _ _ -> noTypeContext $ descend outer A.SizeExpr _ _ -> noTypeContext $ descend outer
A.Conversion _ _ _ _ -> noTypeContext $ descend outer A.Conversion _ _ _ _ -> noTypeContext $ descend outer
A.FunctionCall m n es -> A.FunctionCall m n es ->
@ -910,15 +923,12 @@ inferTypes = applyExplicitM9 doExpression doDimension doSubscript
A.ArrayElemArray aes') A.ArrayElemArray aes')
_ -> diePC m $ formatCode "Table literal is not valid for type %" wantT _ -> diePC m $ formatCode "Table literal is not valid for type %" wantT
where 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 :: A.Type -> [A.ArrayElem] -> PassM (A.Type, [A.ArrayElem])
doElems t [] = return (t, []) doElems t aes
doElems t (ae:aes) = do ts <- mapM (\ae -> doArrayElem t ae >>* fst) aes
= do (t', ae') <- doArrayElem t ae let bestT = foldl betterType t ts
aes' <- sequence [doArrayElem t' ae >>* snd aes' <- mapM (\ae -> doArrayElem bestT ae >>* snd) aes
| ae <- aes] return (bestT, aes')
return (t', ae':aes')
-- An expression: descend into it with the right context. -- An expression: descend into it with the right context.
doArrayElem wantT (A.ArrayElemExpr e) doArrayElem wantT (A.ArrayElemExpr e)
= do e' <- inTypeContext (Just wantT) $ doExpression descend e = do e' <- inTypeContext (Just wantT) $ doExpression descend e