From 5390f6a862e2a46acc1b681d27c2659bbf9ef851 Mon Sep 17 00:00:00 2001 From: hallgren Date: Tue, 23 Jun 2015 12:58:14 +0000 Subject: [PATCH] Bump version of .gfo and .pgf files, improve error messages on version mismatch Becacuse of the new special tokens added to the Symbol type, .gfo and .pgf files produced with the current version of GF can not always be used with older versions of GF and the PGF run-time system. The PGF version number was increased from (2,0) to (2,1). GF can still read version (2,0) and (1,0), so old PGF files continue to work. The GFO version was increased from "GF03" to "GF04". --- src/compiler/GF/Compile/ReadFiles.hs | 14 +++++------ src/compiler/GF/CompileInParallel.hs | 8 ++++--- src/compiler/GF/Grammar/Binary.hs | 35 +++++++++++----------------- src/runtime/haskell/PGF/Binary.hs | 15 +++++++----- 4 files changed, 35 insertions(+), 37 deletions(-) diff --git a/src/compiler/GF/Compile/ReadFiles.hs b/src/compiler/GF/Compile/ReadFiles.hs index 3182e192c..9396b3a2f 100644 --- a/src/compiler/GF/Compile/ReadFiles.hs +++ b/src/compiler/GF/Compile/ReadFiles.hs @@ -20,7 +20,7 @@ module GF.Compile.ReadFiles ( getAllFiles,ModName,ModEnv,importsOfModule, - findFile,gfImports,gfoImports, + findFile,gfImports,gfoImports,VersionTagged(..), parseSource,getOptionsFromFile,getPragmas) where import Prelude hiding (catch) @@ -32,7 +32,7 @@ import GF.Data.Operations import GF.Grammar.Lexer import GF.Grammar.Parser import GF.Grammar.Grammar -import GF.Grammar.Binary(decodeModuleHeader) +import GF.Grammar.Binary(VersionTagged(..),decodeModuleHeader) import System.IO(mkTextEncoding) import GF.Text.Coding(decodeUnicodeIO) @@ -107,10 +107,10 @@ getAllFiles opts ps env file = do case st of CSEnv -> return (st, (name, maybe [] snd mb_envmod)) CSRead -> do let gfo = if isGFO file then file else gf2gfo opts file - mb_imps <- gfoImports gfo - case mb_imps of - Just imps -> return (st,imps) - Nothing + t_imps <- gfoImports gfo + case t_imps of + Tagged imps -> return (st,imps) + WrongVersion | isGFO file -> raise (file ++ " is compiled with different GF version and I can't find the source file") | otherwise -> do imps <- gfImports opts file return (CSComp,imps) @@ -143,7 +143,7 @@ findFile gfoDir ps name = gfImports opts file = importsOfModule `fmap` parseModHeader opts file -gfoImports gfo = fmap importsOfModule `fmap` liftIO (decodeModuleHeader gfo) +gfoImports gfo = fmap importsOfModule `fmap` decodeModuleHeader gfo -------------------------------------------------------------------------------- diff --git a/src/compiler/GF/CompileInParallel.hs b/src/compiler/GF/CompileInParallel.hs index 4f5c0f76b..07c29febd 100644 --- a/src/compiler/GF/CompileInParallel.hs +++ b/src/compiler/GF/CompileInParallel.hs @@ -9,7 +9,7 @@ import qualified GF.System.Directory as D import GF.System.Catch(catch,try) import Data.List(nub,isPrefixOf,intercalate,partition) import qualified Data.Map as M -import GF.Compile.ReadFiles(getOptionsFromFile,findFile,gfImports,gfoImports) +import GF.Compile.ReadFiles(getOptionsFromFile,findFile,gfImports,gfoImports,VersionTagged(..)) import GF.CompileOne(reuseGFO,useTheSource) import GF.Infra.Option import GF.Infra.UseIO @@ -177,8 +177,10 @@ getPathFromFile lib_dir cmdline_opts file = getImports opts file = if isGFO file then gfoImports' file else gfImports opts file where - gfoImports' file = maybe bad return =<< gfoImports file - where bad = raise $ file++": bad .gfo file" + gfoImports' file = check =<< gfoImports file + where + check (Tagged imps) = return imps + check WrongVersion = raise $ file++": .gfo file version mismatch" relativeTo lib_dir cwd path = if length librel Binary (VersionTagged a) where then fmap Tagged get else return WrongVersion +instance Functor VersionTagged where + fmap f (Tagged a) = Tagged (f a) + fmap f WrongVersion = WrongVersion + gfoBinVersion = (b1,b2,b3,b4) where [b1,b2,b3,b4] = map (toEnum.fromEnum) gfoVersion :: [Word8] @@ -324,23 +326,14 @@ decodeModule fpath = liftIO $ check =<< decodeFile' fpath where check (Tagged m) = return m check _ = fail ".gfo file version mismatch" -{- -decodeModuleHeader fpath = decodeFile_ fpath getVersionedMod + +-- | Read just the module header, the returned 'Module' will have an empty body +decodeModuleHeader :: MonadIO io => FilePath -> io (VersionTagged Module) +decodeModuleHeader = liftIO . fmap (fmap conv) . decodeFile' where - getVersionedMod = do - ver <- getGFOVersion - if ver == gfoVersion - then do (m,mtype,mstatus,mflags,mextend,mwith,mopens,med,msrc) <- get - return (Just (m,ModInfo mtype mstatus mflags mextend mwith mopens med msrc Nothing Map.empty)) - else return Nothing ---} ---{- -decodeModuleHeader fpath = fmap check $ decodeFile' fpath - where - check (Tagged (m,mtype,mstatus,mflags,mextend,mwith,mopens,med,msrc)) = - (Just (m,ModInfo mtype mstatus mflags mextend mwith mopens med msrc Nothing Map.empty)) - check _ = Nothing ---} + conv (m,mtype,mstatus,mflags,mextend,mwith,mopens,med,msrc) = + (m,ModInfo mtype mstatus mflags mextend mwith mopens med msrc Nothing Map.empty) + encodeModule :: MonadIO io => FilePath -> SourceModule -> io () encodeModule fpath mo = liftIO $ encodeFile fpath (Tagged mo) diff --git a/src/runtime/haskell/PGF/Binary.hs b/src/runtime/haskell/PGF/Binary.hs index a7f6bf881..e0e50f4be 100644 --- a/src/runtime/haskell/PGF/Binary.hs +++ b/src/runtime/haskell/PGF/Binary.hs @@ -15,7 +15,7 @@ import qualified Data.IntMap as IntMap import Control.Monad pgfMajorVersion, pgfMinorVersion :: Word16 -version@(pgfMajorVersion, pgfMinorVersion) = (2,0) +version@(pgfMajorVersion, pgfMinorVersion) = (2,1) instance Binary PGF where put pgf = do putWord16be pgfMajorVersion @@ -23,11 +23,14 @@ instance Binary PGF where put (gflags pgf) put (absname pgf, abstract pgf) put (concretes pgf) - get = do v1 <- getWord16be - v2 <- getWord16be - case (v1,v2) of - v | v==version -> getPGF' - | v==Old.version -> Old.getPGF' + get = do major<- getWord16be + minor <- getWord16be + let v = (major,minor) + if major==pgfMajorVersion && minor<=pgfMinorVersion + then getPGF' + else if v==Old.version + then Old.getPGF' + else fail $ "Unsupported PGF version "++show (major,minor) getPGF'=do gflags <- get (absname,abstract) <- get