Added ShowOccam and ShowRain type-classes, and changed existing code to use these new show methods in error messages
The function showCode shows code as either occam or Rain depending on the frontend. This is then used by a formatCode function that acts similar to printf, which makes it easy to format error messages that use showCode.
This commit is contained in:
parent
1c5ad805d3
commit
3e342a621c
|
@ -37,6 +37,7 @@ import EvalLiterals
|
||||||
import Metadata
|
import Metadata
|
||||||
import Pass
|
import Pass
|
||||||
import Errors
|
import Errors
|
||||||
|
import ShowCode
|
||||||
import TLP
|
import TLP
|
||||||
import Types
|
import Types
|
||||||
import Utils
|
import Utils
|
||||||
|
@ -117,6 +118,7 @@ data GenOps = GenOps {
|
||||||
genLiteral :: GenOps -> A.LiteralRepr -> CGen (),
|
genLiteral :: GenOps -> A.LiteralRepr -> CGen (),
|
||||||
genLiteralRepr :: GenOps -> A.LiteralRepr -> CGen (),
|
genLiteralRepr :: GenOps -> A.LiteralRepr -> CGen (),
|
||||||
genMissing :: GenOps -> String -> CGen (),
|
genMissing :: GenOps -> String -> CGen (),
|
||||||
|
genMissingC :: GenOps -> CGen String -> CGen (),
|
||||||
genMonadic :: GenOps -> Meta -> A.MonadicOp -> A.Expression -> CGen (),
|
genMonadic :: GenOps -> Meta -> A.MonadicOp -> A.Expression -> CGen (),
|
||||||
genOutput :: GenOps -> A.Variable -> [A.OutputItem] -> CGen (),
|
genOutput :: GenOps -> A.Variable -> [A.OutputItem] -> CGen (),
|
||||||
genOutputCase :: GenOps -> A.Variable -> A.Name -> [A.OutputItem] -> CGen (),
|
genOutputCase :: GenOps -> A.Variable -> A.Name -> [A.OutputItem] -> CGen (),
|
||||||
|
@ -204,6 +206,7 @@ cgenOps = GenOps {
|
||||||
genLiteral = cgenLiteral,
|
genLiteral = cgenLiteral,
|
||||||
genLiteralRepr = cgenLiteralRepr,
|
genLiteralRepr = cgenLiteralRepr,
|
||||||
genMissing = cgenMissing,
|
genMissing = cgenMissing,
|
||||||
|
genMissingC = (\ops x -> x >>= cgenMissing ops),
|
||||||
genMonadic = cgenMonadic,
|
genMonadic = cgenMonadic,
|
||||||
genOutput = cgenOutput,
|
genOutput = cgenOutput,
|
||||||
genOutputCase = cgenOutputCase,
|
genOutputCase = cgenOutputCase,
|
||||||
|
@ -376,7 +379,7 @@ cgenType _ (A.Chan _ _ t) = tell ["Channel *"]
|
||||||
cgenType ops t
|
cgenType ops t
|
||||||
= case call getScalarType ops t of
|
= case call getScalarType ops t of
|
||||||
Just s -> tell [s]
|
Just s -> tell [s]
|
||||||
Nothing -> call genMissing ops $ "genType " ++ show t
|
Nothing -> call genMissingC ops $ formatCode "genType %" t
|
||||||
|
|
||||||
-- | Generate the number of bytes in a type that must have a fixed size.
|
-- | Generate the number of bytes in a type that must have a fixed size.
|
||||||
cgenBytesIn :: GenOps -> A.Type -> Maybe A.Variable -> CGen ()
|
cgenBytesIn :: GenOps -> A.Type -> Maybe A.Variable -> CGen ()
|
||||||
|
@ -423,7 +426,7 @@ cgenBytesIn' _ (A.Chan {}) _
|
||||||
cgenBytesIn' ops t _
|
cgenBytesIn' ops t _
|
||||||
= case call getScalarType ops t of
|
= case call getScalarType ops t of
|
||||||
Just s -> tell ["sizeof (", s, ")"] >> return Nothing
|
Just s -> tell ["sizeof (", s, ")"] >> return Nothing
|
||||||
Nothing -> die $ "genBytesIn' " ++ show t
|
Nothing -> dieC $ formatCode "genBytesIn' %" t
|
||||||
--}}}
|
--}}}
|
||||||
|
|
||||||
--{{{ declarations
|
--{{{ declarations
|
||||||
|
@ -817,7 +820,7 @@ cgenTypeSymbol :: GenOps -> String -> A.Type -> CGen ()
|
||||||
cgenTypeSymbol ops s t
|
cgenTypeSymbol ops s t
|
||||||
= case call getScalarType ops t of
|
= case call getScalarType ops t of
|
||||||
Just ct -> tell ["occam_", s, "_", ct]
|
Just ct -> tell ["occam_", s, "_", ct]
|
||||||
Nothing -> call genMissing ops $ "genTypeSymbol " ++ show t
|
Nothing -> call genMissingC ops $ formatCode "genTypeSymbol %" t
|
||||||
|
|
||||||
cgenIntrinsicFunction :: GenOps -> Meta -> String -> [A.Expression] -> CGen ()
|
cgenIntrinsicFunction :: GenOps -> Meta -> String -> [A.Expression] -> CGen ()
|
||||||
cgenIntrinsicFunction ops m s es
|
cgenIntrinsicFunction ops m s es
|
||||||
|
@ -1503,7 +1506,7 @@ cgenAssign ops m [v] el
|
||||||
tell [" = "]
|
tell [" = "]
|
||||||
call genExpression ops e
|
call genExpression ops e
|
||||||
tell [";\n"]
|
tell [";\n"]
|
||||||
Nothing -> call genMissing ops $ "assignment of type " ++ show t
|
Nothing -> call genMissingC ops $ formatCode "assignment of type %" t
|
||||||
--}}}
|
--}}}
|
||||||
--{{{ input
|
--{{{ input
|
||||||
cgenInput :: GenOps -> A.Variable -> A.InputMode -> CGen ()
|
cgenInput :: GenOps -> A.Variable -> A.InputMode -> CGen ()
|
||||||
|
|
|
@ -87,6 +87,7 @@ import EvalLiterals
|
||||||
import Metadata
|
import Metadata
|
||||||
import Pass
|
import Pass
|
||||||
import Errors
|
import Errors
|
||||||
|
import ShowCode
|
||||||
import TLP
|
import TLP
|
||||||
import Types
|
import Types
|
||||||
import Utils
|
import Utils
|
||||||
|
@ -1079,7 +1080,7 @@ cppgenType _ (A.Any)
|
||||||
cppgenType ops t
|
cppgenType ops t
|
||||||
= case call getScalarType ops t of
|
= case call getScalarType ops t of
|
||||||
Just s -> tell [s]
|
Just s -> tell [s]
|
||||||
Nothing -> call genMissing ops $ "genType " ++ show t
|
Nothing -> call genMissingC ops $ formatCode "genType %" t
|
||||||
|
|
||||||
|
|
||||||
-- | Helper function for prefixing an underscore to a name.
|
-- | Helper function for prefixing an underscore to a name.
|
||||||
|
|
|
@ -127,34 +127,7 @@ data Type =
|
||||||
| Any
|
| Any
|
||||||
| Timer
|
| Timer
|
||||||
| Port Type
|
| Port Type
|
||||||
deriving (Eq, Typeable, Data)
|
deriving (Show, Eq, Typeable, Data)
|
||||||
|
|
||||||
instance Show Type where
|
|
||||||
show Bool = "BOOL"
|
|
||||||
show Byte = "BYTE"
|
|
||||||
show UInt16 = "UINT16"
|
|
||||||
show UInt32 = "UINT32"
|
|
||||||
show UInt64 = "UINT64"
|
|
||||||
show Int = "INT"
|
|
||||||
show Int8 = "INT8"
|
|
||||||
show Int16 = "INT16"
|
|
||||||
show Int32 = "INT32"
|
|
||||||
show Int64 = "INT64"
|
|
||||||
show Real32 = "REAL32"
|
|
||||||
show Real64 = "REAL64"
|
|
||||||
show (Array ds t)
|
|
||||||
= concat [case d of
|
|
||||||
Dimension n -> "[" ++ show n ++ "]"
|
|
||||||
UnknownDimension -> "[]"
|
|
||||||
| d <- ds] ++ show t
|
|
||||||
show (UserDataType n) = nameName n ++ "{data type}"
|
|
||||||
show (Record n) = nameName n ++ "{record}"
|
|
||||||
show (UserProtocol n) = nameName n ++ "{protocol}"
|
|
||||||
show (Chan _ _ t) = "CHAN OF " ++ show t
|
|
||||||
show (Counted ct et) = show ct ++ "::" ++ show et
|
|
||||||
show Any = "ANY"
|
|
||||||
show Timer = "TIMER"
|
|
||||||
show (Port t) = "PORT OF " ++ show t
|
|
||||||
|
|
||||||
-- | An array dimension.
|
-- | An array dimension.
|
||||||
-- Depending on the context, an array type may have empty dimensions, which is
|
-- Depending on the context, an array type may have empty dimensions, which is
|
||||||
|
|
|
@ -24,6 +24,7 @@ import Data.Map (Map)
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import Data.Set (Set)
|
import Data.Set (Set)
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
|
import Control.Monad.Error
|
||||||
import Control.Monad.State
|
import Control.Monad.State
|
||||||
|
|
||||||
import qualified AST as A
|
import qualified AST as A
|
||||||
|
@ -77,7 +78,7 @@ data CompState = CompState {
|
||||||
csAdditionalArgs :: Map String [A.Actual],
|
csAdditionalArgs :: Map String [A.Actual],
|
||||||
csParProcs :: Set A.Name
|
csParProcs :: Set A.Name
|
||||||
}
|
}
|
||||||
deriving (Show, Data, Typeable)
|
deriving (Data, Typeable)
|
||||||
|
|
||||||
instance Show (A.Structured -> A.Structured) where
|
instance Show (A.Structured -> A.Structured) where
|
||||||
show p = "(function on Structured)"
|
show p = "(function on Structured)"
|
||||||
|
@ -247,3 +248,12 @@ makeNonceVariable :: CSM m => String -> Meta -> A.Type -> A.NameType -> A.Abbrev
|
||||||
makeNonceVariable s m t nt am
|
makeNonceVariable s m t nt am
|
||||||
= defineNonce m s (A.Declaration m t) nt am
|
= defineNonce m s (A.Declaration m t) nt am
|
||||||
--}}}
|
--}}}
|
||||||
|
|
||||||
|
diePC :: (CSM m, Die m) => Meta -> m String -> m a
|
||||||
|
diePC m str = str >>= (dieP m)
|
||||||
|
|
||||||
|
dieC :: (CSM m, Die m) => m String -> m a
|
||||||
|
dieC str = str >>= die
|
||||||
|
|
||||||
|
throwErrorC :: (CSM m,MonadError String m) => m String -> m a
|
||||||
|
throwErrorC str = str >>= throwError
|
||||||
|
|
|
@ -37,6 +37,7 @@ import Errors
|
||||||
import EvalLiterals
|
import EvalLiterals
|
||||||
import Metadata
|
import Metadata
|
||||||
import Pass
|
import Pass
|
||||||
|
import ShowCode
|
||||||
import Types
|
import Types
|
||||||
|
|
||||||
-- | Simplify an expression by constant folding, and also return whether it's a
|
-- | Simplify an expression by constant folding, and also return whether it's a
|
||||||
|
@ -167,7 +168,7 @@ evalExpression (A.BytesInType _ t)
|
||||||
= do b <- underlyingType t >>= bytesInType
|
= do b <- underlyingType t >>= bytesInType
|
||||||
case b of
|
case b of
|
||||||
BIJust n -> return $ OccInt (fromIntegral $ n)
|
BIJust n -> return $ OccInt (fromIntegral $ n)
|
||||||
_ -> throwError $ "BYTESIN non-constant-size type " ++ show t ++ " used"
|
_ -> throwErrorC $ formatCode "BYTESIN non-constant-size type % used" t
|
||||||
evalExpression e = throwError "bad expression"
|
evalExpression e = throwError "bad expression"
|
||||||
|
|
||||||
evalMonadicOp :: (forall t. (Num t, Integral t, Bits t) => t -> t) -> OccValue -> EvalM OccValue
|
evalMonadicOp :: (forall t. (Num t, Integral t, Bits t) => t -> t) -> OccValue -> EvalM OccValue
|
||||||
|
|
173
common/ShowCode.hs
Normal file
173
common/ShowCode.hs
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
{-# OPTIONS_GHC -fallow-incoherent-instances #-}
|
||||||
|
{-
|
||||||
|
Tock: a compiler for parallel languages
|
||||||
|
Copyright (C) 2007 University of Kent
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation, either version 2 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-}
|
||||||
|
|
||||||
|
-- | A module with type-classes and functions for displaying code, dependent on the context.
|
||||||
|
-- Primarily, this means showing code as occam in error messages for the occam frontend, and Rain code for the Rain frontend.
|
||||||
|
module ShowCode where
|
||||||
|
|
||||||
|
import Control.Monad.State
|
||||||
|
import Text.Regex
|
||||||
|
import qualified AST as A
|
||||||
|
import CompState
|
||||||
|
|
||||||
|
-- | A type-class that indicates that the data (AST item) is displayable as occam code.
|
||||||
|
class ShowOccam a where
|
||||||
|
showOccam :: a -> String
|
||||||
|
|
||||||
|
-- | A type-class that indicates that the data (AST item) is displayable as Rain code.
|
||||||
|
class ShowRain a where
|
||||||
|
showRain :: a -> String
|
||||||
|
|
||||||
|
-- | Shows the given code (AST item) as either occam or Rain code, depending on which frontend was selected
|
||||||
|
showCode :: (CSM m, ShowOccam a, ShowRain a) => a -> m String
|
||||||
|
showCode o
|
||||||
|
= do st <- get
|
||||||
|
return $ case csFrontend st of
|
||||||
|
FrontendOccam -> showOccam o
|
||||||
|
FrontendRain -> showRain o
|
||||||
|
|
||||||
|
-- | Some type hackery to allow formatCode to take a variable number of functions.
|
||||||
|
class CSM m => ShowCodeFormat a m | a -> m where
|
||||||
|
chain :: [String] -> [m String] -> a
|
||||||
|
|
||||||
|
instance CSM m => ShowCodeFormat (m String) m where
|
||||||
|
chain xs ys = (liftM concat) (sequence $ interleave (map return xs) (ys))
|
||||||
|
where
|
||||||
|
--Given [a,b,c] [1,2], produces [a,1,b,2,c] etc
|
||||||
|
interleave :: [a] -> [a] -> [a]
|
||||||
|
interleave xs [] = xs
|
||||||
|
interleave [] ys = ys
|
||||||
|
interleave (x:xs) (y:ys) = (x:y: (interleave xs ys))
|
||||||
|
|
||||||
|
|
||||||
|
instance (ShowOccam a, ShowRain a, ShowCodeFormat r m, CSM m) => ShowCodeFormat (a -> r) m where
|
||||||
|
chain a x = (\y -> chain a (x ++ [showCode y]))
|
||||||
|
|
||||||
|
|
||||||
|
-- | Formats the given code as either occam or Rain code, depending on the frontend (using showCode).
|
||||||
|
-- Use like this:
|
||||||
|
-- dieC $ formatCode "Types do not match: % and %" ta tb
|
||||||
|
formatCode :: (CSM m,ShowCodeFormat r m) => String -> r
|
||||||
|
formatCode fmt = chain (splitRegex (mkRegex "%") fmt) []
|
||||||
|
|
||||||
|
|
||||||
|
--Type-class instances follow for ShowOccam and ShowRain:
|
||||||
|
|
||||||
|
instance ShowOccam A.Type where
|
||||||
|
showOccam A.Bool = "BOOL"
|
||||||
|
showOccam A.Byte = "BYTE"
|
||||||
|
showOccam A.UInt16 = "UINT16"
|
||||||
|
showOccam A.UInt32 = "UINT32"
|
||||||
|
showOccam A.UInt64 = "UINT64"
|
||||||
|
showOccam A.Int = "INT"
|
||||||
|
showOccam A.Int8 = "INT8"
|
||||||
|
showOccam A.Int16 = "INT16"
|
||||||
|
showOccam A.Int32 = "INT32"
|
||||||
|
showOccam A.Int64 = "INT64"
|
||||||
|
showOccam A.Real32 = "REAL32"
|
||||||
|
showOccam A.Real64 = "REAL64"
|
||||||
|
showOccam (A.Array ds t)
|
||||||
|
= concat [case d of
|
||||||
|
A.Dimension n -> "[" ++ show n ++ "]"
|
||||||
|
A.UnknownDimension -> "[]"
|
||||||
|
| d <- ds] ++ showOccam t
|
||||||
|
showOccam (A.UserDataType n) = A.nameName n ++ "{data type}"
|
||||||
|
showOccam (A.Record n) = A.nameName n ++ "{record}"
|
||||||
|
showOccam (A.UserProtocol n) = A.nameName n ++ "{protocol}"
|
||||||
|
showOccam (A.Chan _ _ t) = "CHAN OF " ++ showOccam t
|
||||||
|
showOccam (A.Counted ct et) = showOccam ct ++ "::" ++ showOccam et
|
||||||
|
showOccam A.Any = "ANY"
|
||||||
|
showOccam A.Timer = "TIMER"
|
||||||
|
showOccam (A.Port t) = "PORT OF " ++ showOccam t
|
||||||
|
|
||||||
|
|
||||||
|
instance ShowRain A.Type where
|
||||||
|
showRain A.Bool = "bool"
|
||||||
|
showRain A.Byte = "uint8"
|
||||||
|
showRain A.UInt16 = "uint16"
|
||||||
|
showRain A.UInt32 = "uint32"
|
||||||
|
showRain A.UInt64 = "uint64"
|
||||||
|
showRain A.Int8 = "sint8"
|
||||||
|
showRain A.Int16 = "sint16"
|
||||||
|
showRain A.Int32 = "sint32"
|
||||||
|
showRain A.Int64 = "int"
|
||||||
|
showRain A.Int = "int"
|
||||||
|
showRain (A.Chan dir attr t)
|
||||||
|
= case dir of
|
||||||
|
A.DirUnknown -> "channel " ++ ao (A.caWritingShared attr) ++ "2" ++ ao (A.caReadingShared attr) ++ " " ++ showRain t
|
||||||
|
A.DirInput -> (if A.caReadingShared attr then "shared" else "") ++ " ?" ++ showRain t
|
||||||
|
A.DirOutput -> (if A.caWritingShared attr then "shared" else "") ++ " !" ++ showRain t
|
||||||
|
where
|
||||||
|
ao :: Bool -> String
|
||||||
|
ao b = if b then "any" else "one"
|
||||||
|
showRain x = "<invalid Rain type: " ++ show x ++ ">"
|
||||||
|
|
||||||
|
instance ShowOccam A.DyadicOp where
|
||||||
|
showOccam A.Add = "+"
|
||||||
|
showOccam A.Subtr = "-"
|
||||||
|
showOccam A.Mul = "*"
|
||||||
|
showOccam A.Div = "/"
|
||||||
|
showOccam A.Rem = "REM"
|
||||||
|
showOccam A.Plus = "PLUS"
|
||||||
|
showOccam A.Minus = "MINUS"
|
||||||
|
showOccam A.Times = "TIMES"
|
||||||
|
showOccam A.BitAnd = "/\\"
|
||||||
|
showOccam A.BitOr = "\\/"
|
||||||
|
showOccam A.BitXor = "><"
|
||||||
|
showOccam A.LeftShift = "<<"
|
||||||
|
showOccam A.RightShift = ">>"
|
||||||
|
showOccam A.And = "AND"
|
||||||
|
showOccam A.Or = "OR"
|
||||||
|
showOccam A.Eq = "="
|
||||||
|
showOccam A.NotEq = "<>"
|
||||||
|
showOccam A.Less = "<"
|
||||||
|
showOccam A.More = ">"
|
||||||
|
showOccam A.LessEq = "<="
|
||||||
|
showOccam A.MoreEq = ">="
|
||||||
|
showOccam A.After = "AFTER"
|
||||||
|
|
||||||
|
|
||||||
|
instance ShowRain A.DyadicOp where
|
||||||
|
showRain A.Div = "/"
|
||||||
|
showRain A.Rem = "%"
|
||||||
|
showRain A.Plus = "+"
|
||||||
|
showRain A.Minus = "-"
|
||||||
|
showRain A.Times = "*"
|
||||||
|
showRain A.And = "and"
|
||||||
|
showRain A.Or = "or"
|
||||||
|
showRain A.Eq = "=="
|
||||||
|
showRain A.NotEq = "<>"
|
||||||
|
showRain A.Less = "<"
|
||||||
|
showRain A.More = ">"
|
||||||
|
showRain A.LessEq = "<="
|
||||||
|
showRain A.MoreEq = ">="
|
||||||
|
showRain x = "<invalid Rain operator: " ++ show x ++ ">"
|
||||||
|
|
||||||
|
instance ShowOccam A.Variable where
|
||||||
|
showOccam (A.Variable _ n) = show n
|
||||||
|
showOccam (A.SubscriptedVariable _ s v) = showOccam v ++ "[" ++ show s ++ "]"
|
||||||
|
showOccam (A.DirectedVariable _ A.DirUnknown v) = showOccam v
|
||||||
|
showOccam (A.DirectedVariable _ A.DirInput v) = showOccam v ++ "?"
|
||||||
|
showOccam (A.DirectedVariable _ A.DirOutput v) = showOccam v ++ "!"
|
||||||
|
|
||||||
|
instance ShowRain A.Variable where
|
||||||
|
showRain (A.Variable _ n) = show n
|
||||||
|
showRain (A.DirectedVariable _ A.DirInput v) = "?" ++ showRain v
|
||||||
|
showRain (A.DirectedVariable _ A.DirOutput v) = "!" ++ showRain v
|
||||||
|
showRain x = "<invalid Rain variable: " ++ show x ++ ">"
|
|
@ -49,6 +49,7 @@ import Control.Monad.State
|
||||||
import Control.Monad.Error
|
import Control.Monad.Error
|
||||||
import Pass
|
import Pass
|
||||||
import CompState
|
import CompState
|
||||||
|
import PrettyShow
|
||||||
import Utils
|
import Utils
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
|
|
||||||
|
@ -332,7 +333,7 @@ testPassShouldFail testName actualPass startStateTrans =
|
||||||
do ret <- runPass actualPass (execState startStateTrans emptyState)
|
do ret <- runPass actualPass (execState startStateTrans emptyState)
|
||||||
case ret of
|
case ret of
|
||||||
(_,Left err) -> return ()
|
(_,Left err) -> return ()
|
||||||
_ -> assertFailure $ testName ++ " pass succeeded when expected to fail, data: " ++ (show ret)
|
_ -> assertFailure $ testName ++ " pass succeeded when expected to fail, data: " ++ (pshow ret)
|
||||||
|
|
||||||
-- | Asserts that a particular variable is defined in the given 'CompState'.
|
-- | Asserts that a particular variable is defined in the given 'CompState'.
|
||||||
assertVarDef ::
|
assertVarDef ::
|
||||||
|
|
|
@ -48,6 +48,7 @@ import Errors
|
||||||
import EvalLiterals
|
import EvalLiterals
|
||||||
import Intrinsics
|
import Intrinsics
|
||||||
import Metadata
|
import Metadata
|
||||||
|
import ShowCode
|
||||||
import Utils
|
import Utils
|
||||||
|
|
||||||
-- | Gets the 'A.SpecType' for a given 'A.Name' from the recorded types in the 'CompState'. Dies with an error if the name is unknown.
|
-- | Gets the 'A.SpecType' for a given 'A.Name' from the recorded types in the 'CompState'. Dies with an error if the name is unknown.
|
||||||
|
@ -124,7 +125,7 @@ plainSubscriptType m sub (A.Array (d:ds) t)
|
||||||
ok = case ds of
|
ok = case ds of
|
||||||
[] -> t
|
[] -> t
|
||||||
_ -> A.Array ds t
|
_ -> A.Array ds t
|
||||||
plainSubscriptType m _ t = dieP m $ "subscript of non-array type " ++ show t
|
plainSubscriptType m _ t = diePC m $ formatCode "subscript of non-array type: %" t
|
||||||
|
|
||||||
-- | Apply a subscript to a type, and return what the type is after it's been
|
-- | Apply a subscript to a type, and return what the type is after it's been
|
||||||
-- subscripted.
|
-- subscripted.
|
||||||
|
@ -145,7 +146,7 @@ subscriptType (A.SubscriptFor m count) t
|
||||||
= sliceType m (makeConstant emptyMeta 0) count t
|
= sliceType m (makeConstant emptyMeta 0) count t
|
||||||
subscriptType (A.SubscriptField m tag) t = typeOfRecordField m t tag
|
subscriptType (A.SubscriptField m tag) t = typeOfRecordField m t tag
|
||||||
subscriptType (A.Subscript m sub) t = plainSubscriptType m sub t
|
subscriptType (A.Subscript m sub) t = plainSubscriptType m sub t
|
||||||
subscriptType _ t = die $ "unsubscriptable type: " ++ show t
|
subscriptType sub t = diePC (findMeta sub) $ formatCode "Unsubscriptable type: %" t
|
||||||
|
|
||||||
-- | The inverse of 'subscriptType': given a type that we know is the result of
|
-- | The inverse of 'subscriptType': given a type that we know is the result of
|
||||||
-- a subscript, return what the type being subscripted is.
|
-- a subscript, return what the type being subscripted is.
|
||||||
|
@ -165,10 +166,10 @@ unsubscriptType (A.Subscript _ sub) t
|
||||||
-- subscriptType with constant 0 as a subscript, but without the checking.
|
-- subscriptType with constant 0 as a subscript, but without the checking.
|
||||||
-- This is used for the couple of cases where we know it's safe and don't want
|
-- This is used for the couple of cases where we know it's safe and don't want
|
||||||
-- the usage check.
|
-- the usage check.
|
||||||
trivialSubscriptType :: (Die m) => A.Type -> m A.Type
|
trivialSubscriptType :: (CSM m, Die m) => A.Type -> m A.Type
|
||||||
trivialSubscriptType (A.Array [d] t) = return t
|
trivialSubscriptType (A.Array [d] t) = return t
|
||||||
trivialSubscriptType (A.Array (d:ds) t) = return $ A.Array ds t
|
trivialSubscriptType (A.Array (d:ds) t) = return $ A.Array ds t
|
||||||
trivialSubscriptType t = die $ "not plain array type: " ++ show t
|
trivialSubscriptType t = dieC $ formatCode "not plain array type: %" t
|
||||||
|
|
||||||
-- | Gets the 'A.Type' of a 'A.Variable' by looking at the types recorded in the 'CompState'.
|
-- | Gets the 'A.Type' of a 'A.Variable' by looking at the types recorded in the 'CompState'.
|
||||||
typeOfVariable :: (CSM m, Die m) => A.Variable -> m A.Type
|
typeOfVariable :: (CSM m, Die m) => A.Variable -> m A.Type
|
||||||
|
|
|
@ -38,6 +38,7 @@ import Intrinsics
|
||||||
import LexOccam
|
import LexOccam
|
||||||
import Metadata
|
import Metadata
|
||||||
import Pass
|
import Pass
|
||||||
|
import ShowCode
|
||||||
import Types
|
import Types
|
||||||
import Utils
|
import Utils
|
||||||
|
|
||||||
|
@ -294,7 +295,7 @@ maybeSliced inner subscripter typer
|
||||||
t <- typer v >>= underlyingType
|
t <- typer v >>= underlyingType
|
||||||
case t of
|
case t of
|
||||||
(A.Array _ _) -> return ()
|
(A.Array _ _) -> return ()
|
||||||
_ -> fail $ "slice of non-array type " ++ show t
|
_ -> fail $ "slice of non-array type " ++ showOccam t
|
||||||
|
|
||||||
e <- intExpr
|
e <- intExpr
|
||||||
sub <- case ff1 of
|
sub <- case ff1 of
|
||||||
|
@ -392,7 +393,7 @@ matchType et rt
|
||||||
else bad
|
else bad
|
||||||
_ -> if rt == et then return () else bad
|
_ -> if rt == et then return () else bad
|
||||||
where
|
where
|
||||||
bad = fail $ "type mismatch (got " ++ show rt ++ "; expected " ++ show et ++ ")"
|
bad = fail $ "type mismatch (got " ++ showOccam rt ++ "; expected " ++ showOccam et ++ ")"
|
||||||
|
|
||||||
-- | Check that two lists of types match (for example, for parallel assignment).
|
-- | Check that two lists of types match (for example, for parallel assignment).
|
||||||
matchTypes :: [A.Type] -> [A.Type] -> OccParser ()
|
matchTypes :: [A.Type] -> [A.Type] -> OccParser ()
|
||||||
|
@ -672,7 +673,7 @@ makeLiteral x@(A.Literal m t lr) wantT
|
||||||
|
|
||||||
typesOK <- isValidLiteralType m t wantT
|
typesOK <- isValidLiteralType m t wantT
|
||||||
when (not typesOK) $
|
when (not typesOK) $
|
||||||
dieP m $ "default type of literal (" ++ show t ++ ") cannot be coerced to desired type (" ++ show wantT ++ ")"
|
dieP m $ "default type of literal (" ++ showOccam t ++ ") cannot be coerced to desired type (" ++ showOccam wantT ++ ")"
|
||||||
|
|
||||||
case (underT, lr) of
|
case (underT, lr) of
|
||||||
-- An array literal.
|
-- An array literal.
|
||||||
|
@ -1936,7 +1937,7 @@ actual (A.Formal am t n)
|
||||||
A.Timer -> var timer
|
A.Timer -> var timer
|
||||||
A.Port _ -> var (portOfType t)
|
A.Port _ -> var (portOfType t)
|
||||||
_ -> var (variableOfType t)
|
_ -> var (variableOfType t)
|
||||||
<?> "actual of type " ++ show t ++ " for " ++ show n
|
<?> "actual of type " ++ showOccam t ++ " for " ++ show n
|
||||||
where
|
where
|
||||||
var inner = liftM (A.ActualVariable am t) inner
|
var inner = liftM (A.ActualVariable am t) inner
|
||||||
--}}}
|
--}}}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import Types
|
||||||
import Control.Monad.State
|
import Control.Monad.State
|
||||||
import CompState
|
import CompState
|
||||||
import Metadata
|
import Metadata
|
||||||
|
import ShowCode
|
||||||
|
|
||||||
|
|
||||||
-- | A pass that records inferred types. Currently the only place where types are inferred is in seqeach\/pareach loops.
|
-- | A pass that records inferred types. Currently the only place where types are inferred is in seqeach\/pareach loops.
|
||||||
|
@ -148,8 +149,7 @@ coerceType :: String -> A.Type -> A.Type -> A.Expression -> PassM A.Expression
|
||||||
coerceType customMsg to from item
|
coerceType customMsg to from item
|
||||||
= if isImplicitConversionRain from to
|
= if isImplicitConversionRain from to
|
||||||
then return $ A.Conversion (findMeta item) A.DefaultConversion to item
|
then return $ A.Conversion (findMeta item) A.DefaultConversion to item
|
||||||
else dieP (findMeta item) $ "Could not perform implicit cast from supplied type: " ++ (show from) ++
|
else diePC (findMeta item) $ (liftM concat) $ sequence [formatCode "Could not perform implicit cast from supplied type: % to expected type: %" from to, return customMsg]
|
||||||
" to expected type: " ++ (show to) ++ customMsg
|
|
||||||
|
|
||||||
|
|
||||||
-- | Checks the types in expressions
|
-- | Checks the types in expressions
|
||||||
|
@ -161,14 +161,14 @@ checkExpressionTypes = everywhereASTM checkExpression
|
||||||
= do tlhs <- typeOfExpression lhs
|
= do tlhs <- typeOfExpression lhs
|
||||||
trhs <- typeOfExpression rhs
|
trhs <- typeOfExpression rhs
|
||||||
if (tlhs == trhs)
|
if (tlhs == trhs)
|
||||||
then (if validOp op tlhs then return e else dieP m $ "Operator: \"" ++ show op ++ "\" is not valid on type: \"" ++ show tlhs)
|
then (if validOp op tlhs then return e else diePC m $ formatCode "Operator: \"%\" is not valid on type: \"%\"" op tlhs)
|
||||||
else if (isIntegerType tlhs && isIntegerType trhs)
|
else if (isIntegerType tlhs && isIntegerType trhs)
|
||||||
then case (leastGeneralSharedTypeRain [tlhs,trhs]) of
|
then case (leastGeneralSharedTypeRain [tlhs,trhs]) of
|
||||||
Nothing -> dieP m $ "Cannot find a suitable type to convert expression to, types are: " ++ show tlhs ++ " and " ++ show trhs
|
Nothing -> diePC m $ formatCode "Cannot find a suitable type to convert expression to, types are: % and %" tlhs trhs
|
||||||
Just t -> if validOp op t then return $ A.Dyadic m op (convert t tlhs lhs) (convert t trhs rhs) else dieP m $
|
Just t -> if validOp op t then return $ A.Dyadic m op (convert t tlhs lhs) (convert t trhs rhs) else diePC m $
|
||||||
"Operator: \"" ++ show op ++ "\" is not valid on type: \"" ++ show tlhs
|
formatCode "Operator: \"%\" is not valid on type: \"%\"" op tlhs
|
||||||
else --The operators are not equal, and are not integers. Therefore this must be an error:
|
else --The operators are not equal, and are not integers. Therefore this must be an error:
|
||||||
dieP m $ "Mis-matched types; no operator applies to types: " ++ show tlhs ++ " and " ++ show trhs
|
diePC m $ formatCode "Mis-matched types; no operator applies to types: % and %" tlhs trhs
|
||||||
checkExpression e@(A.Monadic m op rhs)
|
checkExpression e@(A.Monadic m op rhs)
|
||||||
= do trhs <- typeOfExpression rhs
|
= do trhs <- typeOfExpression rhs
|
||||||
if (op == A.MonadicMinus)
|
if (op == A.MonadicMinus)
|
||||||
|
@ -176,13 +176,13 @@ checkExpressionTypes = everywhereASTM checkExpression
|
||||||
A.Byte -> return $ A.Monadic m op $ convert A.Int16 trhs rhs
|
A.Byte -> return $ A.Monadic m op $ convert A.Int16 trhs rhs
|
||||||
A.UInt16 -> return $ A.Monadic m op $ convert A.Int32 trhs rhs
|
A.UInt16 -> return $ A.Monadic m op $ convert A.Int32 trhs rhs
|
||||||
A.UInt32 -> return $ A.Monadic m op $ convert A.Int64 trhs rhs
|
A.UInt32 -> return $ A.Monadic m op $ convert A.Int64 trhs rhs
|
||||||
A.UInt64 -> dieP m $ "Cannot apply unary minus to type: " ++ show trhs ++ " because there is no type large enough to safely contain the result"
|
A.UInt64 -> diePC m $ formatCode "Cannot apply unary minus to type: % because there is no type large enough to safely contain the result" trhs
|
||||||
_ -> if (isIntegerType trhs) then return e else dieP m $ "Trying to apply unary minus to non-integer type: " ++ show trhs
|
_ -> if (isIntegerType trhs) then return e else diePC m $ formatCode "Trying to apply unary minus to non-integer type: %" trhs
|
||||||
else if (op == A.MonadicNot)
|
else if (op == A.MonadicNot)
|
||||||
then
|
then
|
||||||
case trhs of
|
case trhs of
|
||||||
A.Bool -> return e
|
A.Bool -> return e
|
||||||
_ -> dieP m $ "Cannot apply unary not to non-boolean type: " ++ show trhs
|
_ -> diePC m $ formatCode "Cannot apply unary not to non-boolean type: %" trhs
|
||||||
else dieP m $ "Invalid Rain operator: \"" ++ show op ++ "\""
|
else dieP m $ "Invalid Rain operator: \"" ++ show op ++ "\""
|
||||||
checkExpression e@(A.Conversion m cm dest rhs)
|
checkExpression e@(A.Conversion m cm dest rhs)
|
||||||
= do src <- typeOfExpression rhs
|
= do src <- typeOfExpression rhs
|
||||||
|
@ -190,7 +190,7 @@ checkExpressionTypes = everywhereASTM checkExpression
|
||||||
then return e
|
then return e
|
||||||
else if isImplicitConversionRain src dest
|
else if isImplicitConversionRain src dest
|
||||||
then return e
|
then return e
|
||||||
else dieP m $ "Invalid cast from: " ++ show dest ++ " to: " ++ show src
|
else diePC m $ formatCode "Invalid cast from: % to: %" dest src
|
||||||
checkExpression e = return e
|
checkExpression e = return e
|
||||||
|
|
||||||
convert :: A.Type -> A.Type -> A.Expression -> A.Expression
|
convert :: A.Type -> A.Type -> A.Expression -> A.Expression
|
||||||
|
@ -266,8 +266,8 @@ checkCommTypes = everywhereASTM checkInputOutput
|
||||||
else
|
else
|
||||||
if (innerType == destType)
|
if (innerType == destType)
|
||||||
then return p
|
then return p
|
||||||
else dieP m $ "Mis-matching types; channel: " ++ show chanVar ++ " has inner-type: " ++ show innerType ++
|
else diePC m $ formatCode "Mis-matching types; channel: \"%\" has inner-type: % but destination variable: \"%\" has type: %"
|
||||||
" but destination variable: " ++ show destVar ++ " has type: " ++ show destType
|
chanVar innerType destVar destType
|
||||||
_ -> dieP m $ "Tried to input from a variable that is not of type channel: " ++ show chanVar
|
_ -> dieP m $ "Tried to input from a variable that is not of type channel: " ++ show chanVar
|
||||||
checkInputOutput p@(A.Output m chanVar [A.OutExpression m' srcExp])
|
checkInputOutput p@(A.Output m chanVar [A.OutExpression m' srcExp])
|
||||||
= do chanType <- typeOfVariable chanVar
|
= do chanType <- typeOfVariable chanVar
|
||||||
|
|
Loading…
Reference in New Issue
Block a user