diff --git a/fco2/GenerateC.hs b/fco2/GenerateC.hs index 2f80ef8..6a11ff1 100644 --- a/fco2/GenerateC.hs +++ b/fco2/GenerateC.hs @@ -292,11 +292,7 @@ genArrayLiteralElems aes where genElem :: A.ArrayElem -> CGen () genElem (A.ArrayElemArray aes) = genArrayLiteralElems aes - genElem (A.ArrayElemExpr e) - = do t <- typeOfExpression e - case t of - A.Array _ _ -> missing $ "array literal containing non-literal array: " ++ show e - _ -> genExpression e + genElem (A.ArrayElemExpr e) = genExpression e genByteLiteral :: String -> CGen () genByteLiteral s diff --git a/fco2/Makefile b/fco2/Makefile index d78c515..2abda9d 100644 --- a/fco2/Makefile +++ b/fco2/Makefile @@ -42,6 +42,9 @@ cgtests_targets = $(patsubst %.occ,%,$(cgtests)) all-cgtests: $(cgtests_targets) +clean-cgtests: + rm -f cgtests/cgtest?? cgtests/*.tock.* + haddock: @mkdir -p doc haddock -o doc --html $(sources) diff --git a/fco2/SimplifyExprs.hs b/fco2/SimplifyExprs.hs index fc18b32..066e074 100644 --- a/fco2/SimplifyExprs.hs +++ b/fco2/SimplifyExprs.hs @@ -6,6 +6,7 @@ import Data.Generics import Data.Maybe import qualified AST as A +import Errors import Metadata import ParseState import Types @@ -17,6 +18,7 @@ simplifyExprs = runPasses passes passes = [ ("Convert FUNCTIONs to PROCs", functionsToProcs) , ("Convert AFTER to MINUS", removeAfter) + , ("Expand array literals", expandArrayLiterals) , ("Pull up definitions", pullUp) ] @@ -74,6 +76,30 @@ removeAfter = doGeneric `extM` doExpression return $ A.Dyadic m A.More (A.Dyadic m A.Minus a' b') zero doExpression e = doGeneric e +-- | For array literals that include other arrays, burst them into their elements. +expandArrayLiterals :: Data t => t -> PassM t +expandArrayLiterals = doGeneric `extM` doArrayElem + where + doGeneric :: Data t => t -> PassM t + doGeneric = gmapM expandArrayLiterals + + doArrayElem :: A.ArrayElem -> PassM A.ArrayElem + doArrayElem ae@(A.ArrayElemExpr e) + = do e' <- expandArrayLiterals e + t <- typeOfExpression e' + case t of + A.Array ds _ -> expand ds e + _ -> doGeneric ae + doArrayElem ae = doGeneric ae + + expand :: [A.Dimension] -> A.Expression -> PassM A.ArrayElem + expand [] e = return $ A.ArrayElemExpr e + expand (A.UnknownDimension:_) _ + = die "array literal containing non-literal array of unknown size" + expand (A.Dimension n:ds) e + = liftM A.ArrayElemArray $ sequence [expand ds (A.SubscriptedExpr m (A.Subscript m $ makeConstant m i) e) | i <- [0 .. (n - 1)]] + where m = findMeta e + -- | Find things that need to be moved up to their enclosing Structured, and do -- so. pullUp :: Data t => t -> PassM t diff --git a/fco2/TODO b/fco2/TODO index eb2de25..9641022 100644 --- a/fco2/TODO +++ b/fco2/TODO @@ -35,6 +35,9 @@ names in it replaced appropriately. ## Passes +There should be a mkGeneric which produces a version of doGeneric that prunes +out things we don't need to recurse into -- like Strings. + Come up with an approach to combining simple passes to avoid multiple tree walks (for example, giving passes a "next thing to try" parameter). @@ -80,6 +83,8 @@ Slice checks should not be generated if the slice is known to be safe. PLACE should work. +Array comparisons generate silly code (rather than failing). + ## Long-term If we have constant folding, we're three-quarters of the way towards having an diff --git a/fco2/testcases/multidim-literal.occ b/fco2/testcases/multidim-literal.occ index 71fcf6b..d14a764 100644 --- a/fco2/testcases/multidim-literal.occ +++ b/fco2/testcases/multidim-literal.occ @@ -2,6 +2,21 @@ PROC P () VAL [2][2]INT is IS [[1, 2], [3, 4]]: + VAL [2]INT row IS [42, 24]: + VAL [2][2]INT js IS [row, row]: + VAL [2][2]INT jjs IS [is[0], js[0]]: + VAL [][]INT jjjs IS [is[0], js[0]]: + VAL [][][]INT ks IS [js, js, js]: INT x: - x := is[1][1] + SEQ + x := is[1][1] + ASSERT (x = 4) + ASSERT (row[0] = 42) + ASSERT (js[1][1] = 24) + ASSERT (jjs[0][1] = 2) + ASSERT (jjs[1][1] = 24) + SEQ y = 0 FOR 2 + SEQ x = 0 FOR 2 + ASSERT (jjs[x][y] = jjjs[x][y]) + ASSERT (ks[0][0][0] = 42) :