Generate one file per type, rather than ... quite a few.
This commit is contained in:
@@ -10,7 +10,6 @@ module Add(
|
||||
import Data.Bits((.&.))
|
||||
import Data.Map.Strict(Map)
|
||||
import qualified Data.Map.Strict as Map
|
||||
import File
|
||||
import Gen(toLit)
|
||||
import Generators
|
||||
import Language.Rust.Data.Ident
|
||||
@@ -19,11 +18,12 @@ import Language.Rust.Quote
|
||||
import Language.Rust.Syntax
|
||||
import System.Random(RandomGen)
|
||||
|
||||
import RustModule
|
||||
numTestCases :: Int
|
||||
numTestCases = 3000
|
||||
|
||||
safeAddOps :: File
|
||||
safeAddOps = File {
|
||||
safeAddOps :: RustModule
|
||||
safeAddOps = RustModule {
|
||||
predicate = \ me others -> (me + 64) `elem` others,
|
||||
outputName = "safe_add",
|
||||
isUnsigned = True,
|
||||
@@ -31,8 +31,8 @@ safeAddOps = File {
|
||||
testCase = Just generateSafeTests
|
||||
}
|
||||
|
||||
unsafeAddOps :: File
|
||||
unsafeAddOps = File {
|
||||
unsafeAddOps :: RustModule
|
||||
unsafeAddOps = RustModule {
|
||||
predicate = \ _ _ -> True,
|
||||
outputName = "unsafe_add",
|
||||
isUnsigned = True,
|
||||
@@ -40,8 +40,8 @@ unsafeAddOps = File {
|
||||
testCase = Just generateUnsafeTests
|
||||
}
|
||||
|
||||
safeSignedAddOps :: File
|
||||
safeSignedAddOps = File {
|
||||
safeSignedAddOps :: RustModule
|
||||
safeSignedAddOps = RustModule {
|
||||
predicate = \ me others -> (me + 64) `elem` others,
|
||||
outputName = "safe_sadd",
|
||||
isUnsigned = False,
|
||||
@@ -49,8 +49,8 @@ safeSignedAddOps = File {
|
||||
testCase = Just generateSafeSignedTests
|
||||
}
|
||||
|
||||
unsafeSignedAddOps :: File
|
||||
unsafeSignedAddOps = File {
|
||||
unsafeSignedAddOps :: RustModule
|
||||
unsafeSignedAddOps = RustModule {
|
||||
predicate = \ _ _ -> True,
|
||||
outputName = "unsafe_sadd",
|
||||
isUnsigned = False,
|
||||
|
||||
@@ -4,14 +4,14 @@ module Base(
|
||||
)
|
||||
where
|
||||
|
||||
import File
|
||||
import Language.Rust.Data.Ident
|
||||
import Language.Rust.Data.Position
|
||||
import Language.Rust.Quote
|
||||
import Language.Rust.Syntax
|
||||
import RustModule
|
||||
|
||||
base :: File
|
||||
base = File {
|
||||
base :: RustModule
|
||||
base = RustModule {
|
||||
predicate = \ _ _ -> True,
|
||||
outputName = "base",
|
||||
isUnsigned = True,
|
||||
|
||||
@@ -7,20 +7,20 @@ module BinaryOps(
|
||||
import Data.Bits(xor,(.&.),(.|.))
|
||||
import Data.Map.Strict(Map)
|
||||
import qualified Data.Map.Strict as Map
|
||||
import File
|
||||
import Gen(toLit)
|
||||
import Generators
|
||||
import Language.Rust.Data.Ident
|
||||
import Language.Rust.Data.Position
|
||||
import Language.Rust.Quote
|
||||
import Language.Rust.Syntax
|
||||
import RustModule
|
||||
import System.Random(RandomGen)
|
||||
|
||||
numTestCases :: Int
|
||||
numTestCases = 3000
|
||||
|
||||
binaryOps :: File
|
||||
binaryOps = File {
|
||||
binaryOps :: RustModule
|
||||
binaryOps = RustModule {
|
||||
predicate = \ _ _ -> True,
|
||||
outputName = "binary",
|
||||
isUnsigned = True,
|
||||
|
||||
@@ -4,19 +4,19 @@ module Compare(comparisons, signedComparisons)
|
||||
|
||||
import Data.Map.Strict(Map)
|
||||
import qualified Data.Map.Strict as Map
|
||||
import File
|
||||
import Generators
|
||||
import Language.Rust.Data.Ident
|
||||
import Language.Rust.Data.Position
|
||||
import Language.Rust.Quote
|
||||
import Language.Rust.Syntax
|
||||
import RustModule
|
||||
import System.Random(RandomGen)
|
||||
|
||||
numTestCases :: Int
|
||||
numTestCases = 3000
|
||||
|
||||
comparisons :: File
|
||||
comparisons = File {
|
||||
comparisons :: RustModule
|
||||
comparisons = RustModule {
|
||||
predicate = \ _ _ -> True,
|
||||
outputName = "compare",
|
||||
isUnsigned = True,
|
||||
@@ -24,8 +24,8 @@ comparisons = File {
|
||||
testCase = Just generateTests
|
||||
}
|
||||
|
||||
signedComparisons :: File
|
||||
signedComparisons = File {
|
||||
signedComparisons :: RustModule
|
||||
signedComparisons = RustModule {
|
||||
predicate = \ _ _ -> True,
|
||||
outputName = "scompare",
|
||||
isUnsigned = False,
|
||||
|
||||
@@ -5,15 +5,15 @@ module Conversions(
|
||||
)
|
||||
where
|
||||
|
||||
import File
|
||||
import Gen(toLit)
|
||||
import Language.Rust.Data.Ident
|
||||
import Language.Rust.Data.Position
|
||||
import Language.Rust.Quote
|
||||
import Language.Rust.Syntax
|
||||
import RustModule
|
||||
|
||||
conversions :: File
|
||||
conversions = File {
|
||||
conversions :: RustModule
|
||||
conversions = RustModule {
|
||||
predicate = \ _ _ -> True,
|
||||
outputName = "conversions",
|
||||
isUnsigned = True,
|
||||
@@ -21,8 +21,8 @@ conversions = File {
|
||||
testCase = Nothing
|
||||
}
|
||||
|
||||
signedConversions :: File
|
||||
signedConversions = File {
|
||||
signedConversions :: RustModule
|
||||
signedConversions = RustModule {
|
||||
predicate = \ _ _ -> True,
|
||||
outputName = "sconversions",
|
||||
isUnsigned = False,
|
||||
|
||||
@@ -7,20 +7,20 @@ module CryptoNum(
|
||||
import Data.Bits(testBit)
|
||||
import Data.Map.Strict(Map)
|
||||
import qualified Data.Map.Strict as Map
|
||||
import File
|
||||
import Gen
|
||||
import Generators
|
||||
import Language.Rust.Data.Ident
|
||||
import Language.Rust.Data.Position
|
||||
import Language.Rust.Quote
|
||||
import Language.Rust.Syntax
|
||||
import RustModule
|
||||
import System.Random(RandomGen)
|
||||
|
||||
numTestCases :: Int
|
||||
numTestCases = 3000
|
||||
|
||||
cryptoNum :: File
|
||||
cryptoNum = File {
|
||||
cryptoNum :: RustModule
|
||||
cryptoNum = RustModule {
|
||||
predicate = \ _ _ -> True,
|
||||
outputName = "cryptonum",
|
||||
isUnsigned = True,
|
||||
|
||||
@@ -4,20 +4,20 @@ module Division(divisionOps)
|
||||
|
||||
import Data.Map.Strict(Map)
|
||||
import qualified Data.Map.Strict as Map
|
||||
import File
|
||||
import Gen(toLit)
|
||||
import Generators
|
||||
import Language.Rust.Data.Ident
|
||||
import Language.Rust.Data.Position
|
||||
import Language.Rust.Quote
|
||||
import Language.Rust.Syntax
|
||||
import RustModule
|
||||
import System.Random(RandomGen)
|
||||
|
||||
numTestCases :: Int
|
||||
numTestCases = 3000
|
||||
|
||||
divisionOps :: File
|
||||
divisionOps = File {
|
||||
divisionOps :: RustModule
|
||||
divisionOps = RustModule {
|
||||
predicate = \ _ _ -> True,
|
||||
outputName = "divmod",
|
||||
isUnsigned = True,
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
module File(
|
||||
File(..),
|
||||
Task(..),
|
||||
generateTasks,
|
||||
testFile
|
||||
)
|
||||
where
|
||||
|
||||
import Control.Monad(forM_)
|
||||
import Data.Char(toUpper)
|
||||
import Data.List(isPrefixOf)
|
||||
import Data.Map.Strict(Map)
|
||||
import qualified Data.Map.Strict as Map
|
||||
import Language.Rust.Data.Ident(mkIdent)
|
||||
import Language.Rust.Data.Position(Span)
|
||||
import Language.Rust.Pretty(writeSourceFile)
|
||||
import Language.Rust.Quote(item,sourceFile)
|
||||
import Language.Rust.Syntax(SourceFile)
|
||||
import System.FilePath(dropExtension,splitFileName,takeFileName,(</>))
|
||||
import System.IO(Handle,hPutStrLn)
|
||||
import System.Random(RandomGen(..))
|
||||
|
||||
data File = File {
|
||||
predicate :: Word -> [Word] -> Bool,
|
||||
outputName :: FilePath,
|
||||
isUnsigned :: Bool,
|
||||
generator :: Word -> [Word] -> SourceFile Span,
|
||||
testCase :: forall g. RandomGen g => Maybe (Word -> g -> [Map String String])
|
||||
}
|
||||
|
||||
data Task = Task {
|
||||
outputFile :: FilePath,
|
||||
writer :: Handle -> IO ()
|
||||
}
|
||||
|
||||
testFile :: Bool -> Word -> FilePath
|
||||
testFile True size = "U" ++ show5 size ++ ".test"
|
||||
testFile False size = "I" ++ show5 size ++ ".test"
|
||||
|
||||
show5 :: Word -> String
|
||||
show5 = go . show
|
||||
where
|
||||
go x | length x < 5 = go ('0' : x)
|
||||
| otherwise = x
|
||||
|
||||
generateTasks :: RandomGen g => g -> [File] -> [Word] -> [Task]
|
||||
generateTasks rng files sizes = basicTasks ++ moduleTasks
|
||||
where
|
||||
basicTasks = go rng files sizes
|
||||
moduleTasks = generateModules basicTasks
|
||||
--
|
||||
go :: RandomGen g => g -> [File] -> [Word] -> [Task]
|
||||
go _ [] _ = []
|
||||
go g (_:rest) [] = go g rest sizes
|
||||
go g files'@(file:_) (size:rest)
|
||||
| not (predicate file size sizes) = go g files' rest
|
||||
| otherwise =
|
||||
let (myg, theirg) = split g
|
||||
tasks = go theirg files' rest
|
||||
(signedBit, prefix) | isUnsigned file = ("unsigned", "u")
|
||||
| otherwise = ("signed", "i")
|
||||
mainTask = Task {
|
||||
outputFile = "src" </> signedBit </> (prefix ++ show size) </>
|
||||
outputName file ++ ".rs",
|
||||
writer = \ hndl -> writeSourceFile hndl (generator file size sizes)
|
||||
}
|
||||
in case testCase file of
|
||||
Nothing ->
|
||||
mainTask : tasks
|
||||
Just caseGenerator ->
|
||||
let testTask = Task {
|
||||
outputFile = "testdata" </> outputName file </> testFile (isUnsigned file) size,
|
||||
writer = \ hndl -> writeTestCase hndl (caseGenerator size myg)
|
||||
}
|
||||
in testTask : mainTask : tasks
|
||||
|
||||
generateModules :: [Task] -> [Task]
|
||||
generateModules tasks = Map.foldrWithKey maddModule [] fileMap ++ [signedTask, unsignedTask]
|
||||
where
|
||||
maddModule path mods acc
|
||||
| ("src/unsigned" `isPrefixOf` path) || ("src/signed" `isPrefixOf` path) =
|
||||
let (basePath, lowerName) = splitFileName (init path)
|
||||
upperName = map toUpper lowerName
|
||||
task = Task {
|
||||
outputFile = basePath </> lowerName ++ ".rs",
|
||||
writer = \ hndl ->
|
||||
do forM_ mods $ \ modl ->
|
||||
hPutStrLn hndl ("mod " ++ modl ++ ";")
|
||||
hPutStrLn hndl ("pub use base::" ++ upperName ++ ";")
|
||||
}
|
||||
in task : acc
|
||||
| otherwise =
|
||||
acc
|
||||
fileMap = foldr buildBaseMap Map.empty tasks
|
||||
buildBaseMap task acc =
|
||||
let (dir, fileext) = splitFileName (outputFile task)
|
||||
file = dropExtension fileext
|
||||
in Map.insertWith (++) dir [file] acc
|
||||
--
|
||||
signedTask = moduleTask "signed"
|
||||
unsignedTask = moduleTask "unsigned"
|
||||
moduleTask kind =
|
||||
let mods = Map.foldrWithKey (topModule kind) [] fileMap
|
||||
pubuses = Map.foldrWithKey (pubUse kind) [] fileMap
|
||||
in Task {
|
||||
outputFile = "src" </> (kind ++ ".rs"),
|
||||
writer = \ hndl ->
|
||||
writeSourceFile hndl [sourceFile|
|
||||
$@{mods}
|
||||
$@{pubuses}
|
||||
|]
|
||||
}
|
||||
topModule kind path _ acc
|
||||
| ("src/" ++ kind) `isPrefixOf` path =
|
||||
let lowerName = takeFileName (init path)
|
||||
modl = mkIdent lowerName
|
||||
in [item| mod $$modl; |] : acc
|
||||
| otherwise =
|
||||
acc
|
||||
pubUse kind path _ acc
|
||||
| ("src/" ++ kind) `isPrefixOf` path =
|
||||
let lowerName = takeFileName (init path)
|
||||
tname = mkIdent (map toUpper lowerName)
|
||||
modl = mkIdent lowerName
|
||||
in [item| pub use $$modl::$$tname; |] : acc
|
||||
| otherwise =
|
||||
acc
|
||||
|
||||
|
||||
writeTestCase :: Handle -> [Map String String] -> IO ()
|
||||
writeTestCase hndl tests =
|
||||
forM_ tests $ \ test ->
|
||||
forM_ (Map.toList test) $ \ (key, value) ->
|
||||
hPutStrLn hndl (key ++ ": " ++ value)
|
||||
@@ -8,20 +8,20 @@ module ModInv(
|
||||
import Control.Exception(assert)
|
||||
import Data.Map.Strict(Map)
|
||||
import qualified Data.Map.Strict as Map
|
||||
import File
|
||||
import Generators
|
||||
import GHC.Integer.GMP.Internals(recipModInteger)
|
||||
import Language.Rust.Data.Ident
|
||||
import Language.Rust.Data.Position
|
||||
import Language.Rust.Quote
|
||||
import Language.Rust.Syntax
|
||||
import RustModule
|
||||
import System.Random(RandomGen)
|
||||
|
||||
numTestCases :: Int
|
||||
numTestCases = 100
|
||||
|
||||
generateModInvOps :: File
|
||||
generateModInvOps = File {
|
||||
generateModInvOps :: RustModule
|
||||
generateModInvOps = RustModule {
|
||||
predicate = \ me others -> (me + 64) `elem` others,
|
||||
outputName = "modinv",
|
||||
isUnsigned = True,
|
||||
|
||||
@@ -4,20 +4,20 @@ module ModOps(modulusOps)
|
||||
|
||||
import Data.Map.Strict(Map)
|
||||
import qualified Data.Map.Strict as Map
|
||||
import File
|
||||
import Generators
|
||||
import GHC.Integer.GMP.Internals(powModInteger)
|
||||
import Language.Rust.Data.Ident
|
||||
import Language.Rust.Data.Position
|
||||
import Language.Rust.Quote
|
||||
import Language.Rust.Syntax
|
||||
import RustModule
|
||||
import System.Random(RandomGen)
|
||||
|
||||
numTestCases :: Int
|
||||
numTestCases = 1000
|
||||
|
||||
modulusOps :: File
|
||||
modulusOps = File {
|
||||
modulusOps :: RustModule
|
||||
modulusOps = RustModule {
|
||||
predicate = \ me others -> (me * 2) `elem` others,
|
||||
outputName = "modops",
|
||||
isUnsigned = True,
|
||||
|
||||
@@ -9,7 +9,6 @@ import Data.Bits((.&.))
|
||||
import Data.List(union)
|
||||
import Data.Map.Strict(Map)
|
||||
import qualified Data.Map.Strict as Map
|
||||
import File
|
||||
import Gen(toLit)
|
||||
import Generators
|
||||
import Karatsuba
|
||||
@@ -17,13 +16,14 @@ import Language.Rust.Data.Ident
|
||||
import Language.Rust.Data.Position
|
||||
import Language.Rust.Quote
|
||||
import Language.Rust.Syntax
|
||||
import RustModule
|
||||
import System.Random(RandomGen)
|
||||
|
||||
numTestCases :: Int
|
||||
numTestCases = 3000
|
||||
|
||||
safeMultiplyOps :: File
|
||||
safeMultiplyOps = File {
|
||||
safeMultiplyOps :: RustModule
|
||||
safeMultiplyOps = RustModule {
|
||||
predicate = \ me others -> (me * 2) `elem` others,
|
||||
outputName = "safe_mul",
|
||||
isUnsigned = True,
|
||||
@@ -31,8 +31,8 @@ safeMultiplyOps = File {
|
||||
testCase = Just generateSafeTests
|
||||
}
|
||||
|
||||
unsafeMultiplyOps :: File
|
||||
unsafeMultiplyOps = File {
|
||||
unsafeMultiplyOps :: RustModule
|
||||
unsafeMultiplyOps = RustModule {
|
||||
predicate = \ _ _ -> True,
|
||||
outputName = "unsafe_mul",
|
||||
isUnsigned = True,
|
||||
|
||||
191
generation/src/RustModule.hs
Normal file
191
generation/src/RustModule.hs
Normal file
@@ -0,0 +1,191 @@
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
module RustModule(
|
||||
RustModule(..),
|
||||
Task(..),
|
||||
generateTasks,
|
||||
testFile
|
||||
)
|
||||
where
|
||||
|
||||
import Control.Monad(forM_)
|
||||
import Data.Char(toUpper)
|
||||
import Data.List(isPrefixOf, partition)
|
||||
import Data.Map.Strict(Map)
|
||||
import qualified Data.Map.Strict as Map
|
||||
import Data.Maybe(mapMaybe)
|
||||
import Language.Rust.Data.Ident(mkIdent)
|
||||
import Language.Rust.Data.Position(Span, spanOf)
|
||||
import Language.Rust.Pretty(writeSourceFile)
|
||||
import Language.Rust.Quote(item, sourceFile)
|
||||
import Language.Rust.Syntax(Item(..), SourceFile(..), Visibility(..))
|
||||
import System.IO(Handle,hPutStrLn)
|
||||
import System.Random(RandomGen(..))
|
||||
|
||||
data RustModule = RustModule {
|
||||
predicate :: Word -> [Word] -> Bool,
|
||||
outputName :: String,
|
||||
isUnsigned :: Bool,
|
||||
generator :: Word -> [Word] -> SourceFile Span,
|
||||
testCase :: forall g. RandomGen g => Maybe (Word -> g -> [Map String String])
|
||||
}
|
||||
|
||||
data Task = Task {
|
||||
outputFile :: FilePath,
|
||||
writer :: Handle -> IO ()
|
||||
}
|
||||
|
||||
testFile :: Bool -> Word -> FilePath
|
||||
testFile True size = "U" ++ show5 size ++ ".test"
|
||||
testFile False size = "I" ++ show5 size ++ ".test"
|
||||
|
||||
show5 :: Word -> String
|
||||
show5 = go . show
|
||||
where
|
||||
go x | length x < 5 = go ('0' : x)
|
||||
| otherwise = x
|
||||
|
||||
generateTasks :: RandomGen g => g -> [RustModule] -> [Word] -> [Task]
|
||||
generateTasks rng modules sizes = allTheFiles
|
||||
where
|
||||
allTheFiles = implementationsAndTests ++
|
||||
[lump "src/signed", lump "src/unsigned"]
|
||||
implementationsAndTests = concatMap generateModules sizes
|
||||
--
|
||||
lump prefix =
|
||||
let allFiles = map outputFile implementationsAndTests
|
||||
files = filter (prefix `isPrefixOf`) allFiles
|
||||
moduleFiles = map (drop (length prefix + 1)) files
|
||||
moduleNames = map (takeWhile (/= '.')) moduleFiles
|
||||
moduleIdents = map mkIdent moduleNames
|
||||
types = map (mkIdent . map toUpper) moduleNames
|
||||
mods = map (\ name -> [item| mod $$name; |]) moduleIdents
|
||||
uses = zipWith (\ mname tname -> [item| pub use $$mname::$$tname; |])
|
||||
moduleIdents types
|
||||
file = [sourceFile| $@{mods} $@{uses} |]
|
||||
in Task (prefix ++ ".rs") (\hndl -> writeSourceFile hndl file)
|
||||
--
|
||||
generateModules size =
|
||||
let modules' = filter (\m -> predicate m size sizes) modules
|
||||
(umodules, smodules) = partition isUnsigned modules'
|
||||
unsignedTasks = generateImplementations "U" size umodules
|
||||
signedTasks = generateImplementations "I" size smodules
|
||||
in unsignedTasks ++ signedTasks ++ mapMaybe (generateTests size rng) modules'
|
||||
--
|
||||
generateImplementations startsWith size modules'
|
||||
| null modules' = []
|
||||
| otherwise =
|
||||
let name = mkIdent (startsWith ++ show size)
|
||||
baseInclude = [item| pub use self::base::$$name; |]
|
||||
moduleSources = map (generateSubmodule size sizes) modules'
|
||||
moduleFile | startsWith == "I" = "src/signed/i" ++ show size ++ ".rs"
|
||||
| otherwise = "src/unsigned/u" ++ show size ++ ".rs"
|
||||
allSource = SourceFile Nothing [] (baseInclude : moduleSources)
|
||||
in [Task moduleFile (\ hndl -> writeSourceFile hndl allSource)]
|
||||
|
||||
generateSubmodule :: Word -> [Word] -> RustModule -> Item Span
|
||||
generateSubmodule size allSizes m =
|
||||
let SourceFile _ attrs internals = generator m size allSizes
|
||||
modName = mkIdent (outputName m)
|
||||
modSpan = spanOf internals
|
||||
in Mod attrs CrateV modName (Just internals) modSpan
|
||||
|
||||
generateTests :: RandomGen g =>
|
||||
Word -> g ->
|
||||
RustModule ->
|
||||
Maybe Task
|
||||
generateTests size rng m = fmap builder (testCase m)
|
||||
where
|
||||
builder testGeneration =
|
||||
let outFile = "testdata/" ++ outputName m ++ "/" ++ testFile (isUnsigned m) size
|
||||
testGenAction hndl = writeTestCase hndl (testGeneration size (snd (split rng)))
|
||||
in Task outFile testGenAction
|
||||
|
||||
-- basicTasks ++ moduleTasks
|
||||
-- where
|
||||
-- basicTasks = go rng files sizes
|
||||
-- moduleTasks = generateModules basicTasks
|
||||
-- --
|
||||
-- go :: RandomGen g => g -> [RustModule] -> [Word] -> [Task]
|
||||
-- go _ [] _ = []
|
||||
-- go g (_:rest) [] = go g rest sizes
|
||||
-- go g files'@(file:_) (size:rest)
|
||||
-- | not (predicate file size sizes) = go g files' rest
|
||||
-- | otherwise =
|
||||
-- let (myg, theirg) = split g
|
||||
-- tasks = go theirg files' rest
|
||||
-- (signedBit, prefix) | isUnsigned file = ("unsigned", "u")
|
||||
-- | otherwise = ("signed", "i")
|
||||
-- mainTask = Task {
|
||||
-- outputFile = "src" </> signedBit </> (prefix ++ show size) </>
|
||||
-- outputName file ++ ".rs",
|
||||
-- writer = \ hndl -> writeSourceFile hndl (generator file size sizes)
|
||||
-- }
|
||||
-- in case testCase file of
|
||||
-- Nothing ->
|
||||
-- mainTask : tasks
|
||||
-- Just caseGenerator ->
|
||||
-- let testTask = Task {
|
||||
-- outputFile = "testdata" </> outputName file </> testFile (isUnsigned file) size,
|
||||
-- writer = \ hndl -> writeTestCase hndl (caseGenerator size myg)
|
||||
-- }
|
||||
-- in testTask : mainTask : tasks
|
||||
--
|
||||
--generateModules :: [Task] -> [Task]
|
||||
--generateModules tasks = Map.foldrWithKey maddModule [] fileMap ++ [signedTask, unsignedTask]
|
||||
-- where
|
||||
-- maddModule path mods acc
|
||||
-- | ("src/unsigned" `isPrefixOf` path) || ("src/signed" `isPrefixOf` path) =
|
||||
-- let (basePath, lowerName) = splitFileName (init path)
|
||||
-- upperName = map toUpper lowerName
|
||||
-- task = Task {
|
||||
-- outputFile = basePath </> lowerName ++ ".rs",
|
||||
-- writer = \ hndl ->
|
||||
-- do forM_ mods $ \ modl ->
|
||||
-- hPutStrLn hndl ("mod " ++ modl ++ ";")
|
||||
-- hPutStrLn hndl ("pub use base::" ++ upperName ++ ";")
|
||||
-- }
|
||||
-- in task : acc
|
||||
-- | otherwise =
|
||||
-- acc
|
||||
-- fileMap = foldr buildBaseMap Map.empty tasks
|
||||
-- buildBaseMap task acc =
|
||||
-- let (dir, fileext) = splitFileName (outputFile task)
|
||||
-- file = dropExtension fileext
|
||||
-- in Map.insertWith (++) dir [file] acc
|
||||
-- --
|
||||
-- signedTask = moduleTask "signed"
|
||||
-- unsignedTask = moduleTask "unsigned"
|
||||
-- moduleTask kind =
|
||||
-- let mods = Map.foldrWithKey (topModule kind) [] fileMap
|
||||
-- pubuses = Map.foldrWithKey (pubUse kind) [] fileMap
|
||||
-- in Task {
|
||||
-- outputFile = "src" </> (kind ++ ".rs"),
|
||||
-- writer = \ hndl ->
|
||||
-- writeSourceFile hndl [sourceFile|
|
||||
-- $@{mods}
|
||||
-- $@{pubuses}
|
||||
-- |]
|
||||
-- }
|
||||
-- topModule kind path _ acc
|
||||
-- | ("src/" ++ kind) `isPrefixOf` path =
|
||||
-- let lowerName = takeFileName (init path)
|
||||
-- modl = mkIdent lowerName
|
||||
-- in [item| mod $$modl; |] : acc
|
||||
-- | otherwise =
|
||||
-- acc
|
||||
-- pubUse kind path _ acc
|
||||
-- | ("src/" ++ kind) `isPrefixOf` path =
|
||||
-- let lowerName = takeFileName (init path)
|
||||
-- tname = mkIdent (map toUpper lowerName)
|
||||
-- modl = mkIdent lowerName
|
||||
-- in [item| pub use $$modl::$$tname; |] : acc
|
||||
-- | otherwise =
|
||||
-- acc
|
||||
--
|
||||
--
|
||||
writeTestCase :: Handle -> [Map String String] -> IO ()
|
||||
writeTestCase hndl tests =
|
||||
forM_ tests $ \ test ->
|
||||
forM_ (Map.toList test) $ \ (key, value) ->
|
||||
hPutStrLn hndl (key ++ ": " ++ value)
|
||||
@@ -8,20 +8,20 @@ module Scale(
|
||||
import Data.Bits((.&.))
|
||||
import Data.Map.Strict(Map)
|
||||
import qualified Data.Map.Strict as Map
|
||||
import File
|
||||
import Gen(toLit)
|
||||
import Generators
|
||||
import Language.Rust.Data.Ident
|
||||
import Language.Rust.Data.Position
|
||||
import Language.Rust.Quote
|
||||
import Language.Rust.Syntax
|
||||
import RustModule
|
||||
import System.Random(RandomGen)
|
||||
|
||||
numTestCases :: Int
|
||||
numTestCases = 3000
|
||||
|
||||
safeScaleOps :: File
|
||||
safeScaleOps = File {
|
||||
safeScaleOps :: RustModule
|
||||
safeScaleOps = RustModule {
|
||||
predicate = \ me others -> (me + 64) `elem` others,
|
||||
outputName = "safe_scale",
|
||||
isUnsigned = True,
|
||||
@@ -29,8 +29,8 @@ safeScaleOps = File {
|
||||
testCase = Just generateSafeTests
|
||||
}
|
||||
|
||||
unsafeScaleOps :: File
|
||||
unsafeScaleOps = File {
|
||||
unsafeScaleOps :: RustModule
|
||||
unsafeScaleOps = RustModule {
|
||||
predicate = \ _ _ -> True,
|
||||
outputName = "unsafe_scale",
|
||||
isUnsigned = True,
|
||||
|
||||
@@ -5,20 +5,20 @@ module Shift(shiftOps, signedShiftOps)
|
||||
import Data.Bits(shiftL,shiftR)
|
||||
import Data.Map.Strict(Map)
|
||||
import qualified Data.Map.Strict as Map
|
||||
import File
|
||||
import Gen(toLit)
|
||||
import Generators
|
||||
import Language.Rust.Data.Ident
|
||||
import Language.Rust.Data.Position
|
||||
import Language.Rust.Quote
|
||||
import Language.Rust.Syntax
|
||||
import RustModule
|
||||
import System.Random(RandomGen)
|
||||
|
||||
numTestCases :: Int
|
||||
numTestCases = 3000
|
||||
|
||||
shiftOps :: File
|
||||
shiftOps = File {
|
||||
shiftOps :: RustModule
|
||||
shiftOps = RustModule {
|
||||
predicate = \ _ _ -> True,
|
||||
outputName = "shift",
|
||||
isUnsigned = True,
|
||||
@@ -26,8 +26,8 @@ shiftOps = File {
|
||||
testCase = Just generateTests
|
||||
}
|
||||
|
||||
signedShiftOps :: File
|
||||
signedShiftOps = File {
|
||||
signedShiftOps :: RustModule
|
||||
signedShiftOps = RustModule {
|
||||
predicate = \ _ _ -> True,
|
||||
outputName = "sshift",
|
||||
isUnsigned = False,
|
||||
|
||||
@@ -2,15 +2,14 @@
|
||||
module Signed(signedBaseOps)
|
||||
where
|
||||
|
||||
import File
|
||||
import Language.Rust.Data.Ident
|
||||
import Language.Rust.Data.Position
|
||||
import Language.Rust.Quote
|
||||
import Language.Rust.Syntax
|
||||
import RustModule
|
||||
|
||||
|
||||
signedBaseOps :: File
|
||||
signedBaseOps = File {
|
||||
signedBaseOps :: RustModule
|
||||
signedBaseOps = RustModule {
|
||||
predicate = const (const True),
|
||||
outputName = "base",
|
||||
isUnsigned = False,
|
||||
|
||||
@@ -10,20 +10,20 @@ module Subtract(
|
||||
import Data.Bits((.&.))
|
||||
import Data.Map.Strict(Map)
|
||||
import qualified Data.Map.Strict as Map
|
||||
import File
|
||||
import Gen(toLit)
|
||||
import Generators
|
||||
import Language.Rust.Data.Ident
|
||||
import Language.Rust.Data.Position
|
||||
import Language.Rust.Quote
|
||||
import Language.Rust.Syntax
|
||||
import RustModule
|
||||
import System.Random(RandomGen)
|
||||
|
||||
numTestCases :: Int
|
||||
numTestCases = 3000
|
||||
|
||||
safeSubtractOps :: File
|
||||
safeSubtractOps = File {
|
||||
safeSubtractOps :: RustModule
|
||||
safeSubtractOps = RustModule {
|
||||
predicate = \ me others -> (me + 64) `elem` others,
|
||||
outputName = "safe_sub",
|
||||
isUnsigned = True,
|
||||
@@ -31,8 +31,8 @@ safeSubtractOps = File {
|
||||
testCase = Just generateSafeTests
|
||||
}
|
||||
|
||||
safeSignedSubtractOps :: File
|
||||
safeSignedSubtractOps = File {
|
||||
safeSignedSubtractOps :: RustModule
|
||||
safeSignedSubtractOps = RustModule {
|
||||
predicate = \ me others -> (me + 64) `elem` others,
|
||||
outputName = "safe_ssub",
|
||||
isUnsigned = False,
|
||||
@@ -40,8 +40,8 @@ safeSignedSubtractOps = File {
|
||||
testCase = Just generateSafeSignedTests
|
||||
}
|
||||
|
||||
unsafeSubtractOps :: File
|
||||
unsafeSubtractOps = File {
|
||||
unsafeSubtractOps :: RustModule
|
||||
unsafeSubtractOps = RustModule {
|
||||
predicate = \ _ _ -> True,
|
||||
outputName = "unsafe_sub",
|
||||
isUnsigned = True,
|
||||
@@ -49,8 +49,8 @@ unsafeSubtractOps = File {
|
||||
testCase = Just generateUnsafeTests
|
||||
}
|
||||
|
||||
unsafeSignedSubtractOps :: File
|
||||
unsafeSignedSubtractOps = File {
|
||||
unsafeSignedSubtractOps :: RustModule
|
||||
unsafeSignedSubtractOps = RustModule {
|
||||
predicate = \ _ _ -> True,
|
||||
outputName = "unsafe_ssub",
|
||||
isUnsigned = False,
|
||||
|
||||
Reference in New Issue
Block a user