Generate one file per type, rather than ... quite a few.

This commit is contained in:
2020-03-01 15:51:35 -08:00
parent b995c1705f
commit 71451617f9
18 changed files with 260 additions and 206 deletions

View File

@@ -13,11 +13,11 @@ import CryptoNum(cryptoNum)
import Control.Monad(forM_,unless) import Control.Monad(forM_,unless)
import Data.Text.Lazy(Text, pack) import Data.Text.Lazy(Text, pack)
import Division(divisionOps) import Division(divisionOps)
import File(File,Task(..),generateTasks)
import GHC.Conc(getNumCapabilities) import GHC.Conc(getNumCapabilities)
import ModInv(generateModInvOps) import ModInv(generateModInvOps)
import ModOps(modulusOps) import ModOps(modulusOps)
import Multiply(safeMultiplyOps, unsafeMultiplyOps) import Multiply(safeMultiplyOps, unsafeMultiplyOps)
import RustModule(RustModule,Task(..),generateTasks)
import Scale(safeScaleOps, unsafeScaleOps) import Scale(safeScaleOps, unsafeScaleOps)
import Shift(shiftOps, signedShiftOps) import Shift(shiftOps, signedShiftOps)
import Signed(signedBaseOps) import Signed(signedBaseOps)
@@ -39,7 +39,7 @@ highestBitsize = 512
bitsizes :: [Word] bitsizes :: [Word]
bitsizes = [lowestBitsize,lowestBitsize+64..highestBitsize] bitsizes = [lowestBitsize,lowestBitsize+64..highestBitsize]
unsignedFiles :: [File] unsignedFiles :: [RustModule]
unsignedFiles = [ unsignedFiles = [
base base
, binaryOps , binaryOps
@@ -60,7 +60,7 @@ unsignedFiles = [
, unsafeSubtractOps , unsafeSubtractOps
] ]
signedFiles :: [File] signedFiles :: [RustModule]
signedFiles = [ signedFiles = [
safeSignedAddOps safeSignedAddOps
, safeSignedSubtractOps , safeSignedSubtractOps
@@ -72,7 +72,7 @@ signedFiles = [
, unsafeSignedSubtractOps , unsafeSignedSubtractOps
] ]
allFiles :: [File] allFiles :: [RustModule]
allFiles = unsignedFiles ++ signedFiles allFiles = unsignedFiles ++ signedFiles
printLast :: Progress String -> Timing -> Text printLast :: Progress String -> Timing -> Text

View File

@@ -37,13 +37,13 @@ library
Conversions, Conversions,
CryptoNum, CryptoNum,
Division, Division,
File,
Gen, Gen,
Generators, Generators,
Karatsuba, Karatsuba,
ModInv, ModInv,
ModOps, ModOps,
Multiply, Multiply,
RustModule,
Scale, Scale,
Shift, Shift,
Signed, Signed,

View File

@@ -10,7 +10,6 @@ module Add(
import Data.Bits((.&.)) import Data.Bits((.&.))
import Data.Map.Strict(Map) import Data.Map.Strict(Map)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import File
import Gen(toLit) import Gen(toLit)
import Generators import Generators
import Language.Rust.Data.Ident import Language.Rust.Data.Ident
@@ -19,11 +18,12 @@ import Language.Rust.Quote
import Language.Rust.Syntax import Language.Rust.Syntax
import System.Random(RandomGen) import System.Random(RandomGen)
import RustModule
numTestCases :: Int numTestCases :: Int
numTestCases = 3000 numTestCases = 3000
safeAddOps :: File safeAddOps :: RustModule
safeAddOps = File { safeAddOps = RustModule {
predicate = \ me others -> (me + 64) `elem` others, predicate = \ me others -> (me + 64) `elem` others,
outputName = "safe_add", outputName = "safe_add",
isUnsigned = True, isUnsigned = True,
@@ -31,8 +31,8 @@ safeAddOps = File {
testCase = Just generateSafeTests testCase = Just generateSafeTests
} }
unsafeAddOps :: File unsafeAddOps :: RustModule
unsafeAddOps = File { unsafeAddOps = RustModule {
predicate = \ _ _ -> True, predicate = \ _ _ -> True,
outputName = "unsafe_add", outputName = "unsafe_add",
isUnsigned = True, isUnsigned = True,
@@ -40,8 +40,8 @@ unsafeAddOps = File {
testCase = Just generateUnsafeTests testCase = Just generateUnsafeTests
} }
safeSignedAddOps :: File safeSignedAddOps :: RustModule
safeSignedAddOps = File { safeSignedAddOps = RustModule {
predicate = \ me others -> (me + 64) `elem` others, predicate = \ me others -> (me + 64) `elem` others,
outputName = "safe_sadd", outputName = "safe_sadd",
isUnsigned = False, isUnsigned = False,
@@ -49,8 +49,8 @@ safeSignedAddOps = File {
testCase = Just generateSafeSignedTests testCase = Just generateSafeSignedTests
} }
unsafeSignedAddOps :: File unsafeSignedAddOps :: RustModule
unsafeSignedAddOps = File { unsafeSignedAddOps = RustModule {
predicate = \ _ _ -> True, predicate = \ _ _ -> True,
outputName = "unsafe_sadd", outputName = "unsafe_sadd",
isUnsigned = False, isUnsigned = False,

View File

@@ -4,14 +4,14 @@ module Base(
) )
where where
import File
import Language.Rust.Data.Ident import Language.Rust.Data.Ident
import Language.Rust.Data.Position import Language.Rust.Data.Position
import Language.Rust.Quote import Language.Rust.Quote
import Language.Rust.Syntax import Language.Rust.Syntax
import RustModule
base :: File base :: RustModule
base = File { base = RustModule {
predicate = \ _ _ -> True, predicate = \ _ _ -> True,
outputName = "base", outputName = "base",
isUnsigned = True, isUnsigned = True,

View File

@@ -7,20 +7,20 @@ module BinaryOps(
import Data.Bits(xor,(.&.),(.|.)) import Data.Bits(xor,(.&.),(.|.))
import Data.Map.Strict(Map) import Data.Map.Strict(Map)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import File
import Gen(toLit) import Gen(toLit)
import Generators import Generators
import Language.Rust.Data.Ident import Language.Rust.Data.Ident
import Language.Rust.Data.Position import Language.Rust.Data.Position
import Language.Rust.Quote import Language.Rust.Quote
import Language.Rust.Syntax import Language.Rust.Syntax
import RustModule
import System.Random(RandomGen) import System.Random(RandomGen)
numTestCases :: Int numTestCases :: Int
numTestCases = 3000 numTestCases = 3000
binaryOps :: File binaryOps :: RustModule
binaryOps = File { binaryOps = RustModule {
predicate = \ _ _ -> True, predicate = \ _ _ -> True,
outputName = "binary", outputName = "binary",
isUnsigned = True, isUnsigned = True,

View File

@@ -4,19 +4,19 @@ module Compare(comparisons, signedComparisons)
import Data.Map.Strict(Map) import Data.Map.Strict(Map)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import File
import Generators import Generators
import Language.Rust.Data.Ident import Language.Rust.Data.Ident
import Language.Rust.Data.Position import Language.Rust.Data.Position
import Language.Rust.Quote import Language.Rust.Quote
import Language.Rust.Syntax import Language.Rust.Syntax
import RustModule
import System.Random(RandomGen) import System.Random(RandomGen)
numTestCases :: Int numTestCases :: Int
numTestCases = 3000 numTestCases = 3000
comparisons :: File comparisons :: RustModule
comparisons = File { comparisons = RustModule {
predicate = \ _ _ -> True, predicate = \ _ _ -> True,
outputName = "compare", outputName = "compare",
isUnsigned = True, isUnsigned = True,
@@ -24,8 +24,8 @@ comparisons = File {
testCase = Just generateTests testCase = Just generateTests
} }
signedComparisons :: File signedComparisons :: RustModule
signedComparisons = File { signedComparisons = RustModule {
predicate = \ _ _ -> True, predicate = \ _ _ -> True,
outputName = "scompare", outputName = "scompare",
isUnsigned = False, isUnsigned = False,

View File

@@ -5,15 +5,15 @@ module Conversions(
) )
where where
import File
import Gen(toLit) import Gen(toLit)
import Language.Rust.Data.Ident import Language.Rust.Data.Ident
import Language.Rust.Data.Position import Language.Rust.Data.Position
import Language.Rust.Quote import Language.Rust.Quote
import Language.Rust.Syntax import Language.Rust.Syntax
import RustModule
conversions :: File conversions :: RustModule
conversions = File { conversions = RustModule {
predicate = \ _ _ -> True, predicate = \ _ _ -> True,
outputName = "conversions", outputName = "conversions",
isUnsigned = True, isUnsigned = True,
@@ -21,8 +21,8 @@ conversions = File {
testCase = Nothing testCase = Nothing
} }
signedConversions :: File signedConversions :: RustModule
signedConversions = File { signedConversions = RustModule {
predicate = \ _ _ -> True, predicate = \ _ _ -> True,
outputName = "sconversions", outputName = "sconversions",
isUnsigned = False, isUnsigned = False,

View File

@@ -7,20 +7,20 @@ module CryptoNum(
import Data.Bits(testBit) import Data.Bits(testBit)
import Data.Map.Strict(Map) import Data.Map.Strict(Map)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import File
import Gen import Gen
import Generators import Generators
import Language.Rust.Data.Ident import Language.Rust.Data.Ident
import Language.Rust.Data.Position import Language.Rust.Data.Position
import Language.Rust.Quote import Language.Rust.Quote
import Language.Rust.Syntax import Language.Rust.Syntax
import RustModule
import System.Random(RandomGen) import System.Random(RandomGen)
numTestCases :: Int numTestCases :: Int
numTestCases = 3000 numTestCases = 3000
cryptoNum :: File cryptoNum :: RustModule
cryptoNum = File { cryptoNum = RustModule {
predicate = \ _ _ -> True, predicate = \ _ _ -> True,
outputName = "cryptonum", outputName = "cryptonum",
isUnsigned = True, isUnsigned = True,

View File

@@ -4,20 +4,20 @@ module Division(divisionOps)
import Data.Map.Strict(Map) import Data.Map.Strict(Map)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import File
import Gen(toLit) import Gen(toLit)
import Generators import Generators
import Language.Rust.Data.Ident import Language.Rust.Data.Ident
import Language.Rust.Data.Position import Language.Rust.Data.Position
import Language.Rust.Quote import Language.Rust.Quote
import Language.Rust.Syntax import Language.Rust.Syntax
import RustModule
import System.Random(RandomGen) import System.Random(RandomGen)
numTestCases :: Int numTestCases :: Int
numTestCases = 3000 numTestCases = 3000
divisionOps :: File divisionOps :: RustModule
divisionOps = File { divisionOps = RustModule {
predicate = \ _ _ -> True, predicate = \ _ _ -> True,
outputName = "divmod", outputName = "divmod",
isUnsigned = True, isUnsigned = True,

View File

@@ -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)

View File

@@ -8,20 +8,20 @@ module ModInv(
import Control.Exception(assert) import Control.Exception(assert)
import Data.Map.Strict(Map) import Data.Map.Strict(Map)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import File
import Generators import Generators
import GHC.Integer.GMP.Internals(recipModInteger) import GHC.Integer.GMP.Internals(recipModInteger)
import Language.Rust.Data.Ident import Language.Rust.Data.Ident
import Language.Rust.Data.Position import Language.Rust.Data.Position
import Language.Rust.Quote import Language.Rust.Quote
import Language.Rust.Syntax import Language.Rust.Syntax
import RustModule
import System.Random(RandomGen) import System.Random(RandomGen)
numTestCases :: Int numTestCases :: Int
numTestCases = 100 numTestCases = 100
generateModInvOps :: File generateModInvOps :: RustModule
generateModInvOps = File { generateModInvOps = RustModule {
predicate = \ me others -> (me + 64) `elem` others, predicate = \ me others -> (me + 64) `elem` others,
outputName = "modinv", outputName = "modinv",
isUnsigned = True, isUnsigned = True,

View File

@@ -4,20 +4,20 @@ module ModOps(modulusOps)
import Data.Map.Strict(Map) import Data.Map.Strict(Map)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import File
import Generators import Generators
import GHC.Integer.GMP.Internals(powModInteger) import GHC.Integer.GMP.Internals(powModInteger)
import Language.Rust.Data.Ident import Language.Rust.Data.Ident
import Language.Rust.Data.Position import Language.Rust.Data.Position
import Language.Rust.Quote import Language.Rust.Quote
import Language.Rust.Syntax import Language.Rust.Syntax
import RustModule
import System.Random(RandomGen) import System.Random(RandomGen)
numTestCases :: Int numTestCases :: Int
numTestCases = 1000 numTestCases = 1000
modulusOps :: File modulusOps :: RustModule
modulusOps = File { modulusOps = RustModule {
predicate = \ me others -> (me * 2) `elem` others, predicate = \ me others -> (me * 2) `elem` others,
outputName = "modops", outputName = "modops",
isUnsigned = True, isUnsigned = True,

View File

@@ -9,7 +9,6 @@ import Data.Bits((.&.))
import Data.List(union) import Data.List(union)
import Data.Map.Strict(Map) import Data.Map.Strict(Map)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import File
import Gen(toLit) import Gen(toLit)
import Generators import Generators
import Karatsuba import Karatsuba
@@ -17,13 +16,14 @@ import Language.Rust.Data.Ident
import Language.Rust.Data.Position import Language.Rust.Data.Position
import Language.Rust.Quote import Language.Rust.Quote
import Language.Rust.Syntax import Language.Rust.Syntax
import RustModule
import System.Random(RandomGen) import System.Random(RandomGen)
numTestCases :: Int numTestCases :: Int
numTestCases = 3000 numTestCases = 3000
safeMultiplyOps :: File safeMultiplyOps :: RustModule
safeMultiplyOps = File { safeMultiplyOps = RustModule {
predicate = \ me others -> (me * 2) `elem` others, predicate = \ me others -> (me * 2) `elem` others,
outputName = "safe_mul", outputName = "safe_mul",
isUnsigned = True, isUnsigned = True,
@@ -31,8 +31,8 @@ safeMultiplyOps = File {
testCase = Just generateSafeTests testCase = Just generateSafeTests
} }
unsafeMultiplyOps :: File unsafeMultiplyOps :: RustModule
unsafeMultiplyOps = File { unsafeMultiplyOps = RustModule {
predicate = \ _ _ -> True, predicate = \ _ _ -> True,
outputName = "unsafe_mul", outputName = "unsafe_mul",
isUnsigned = True, isUnsigned = True,

View 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)

View File

@@ -8,20 +8,20 @@ module Scale(
import Data.Bits((.&.)) import Data.Bits((.&.))
import Data.Map.Strict(Map) import Data.Map.Strict(Map)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import File
import Gen(toLit) import Gen(toLit)
import Generators import Generators
import Language.Rust.Data.Ident import Language.Rust.Data.Ident
import Language.Rust.Data.Position import Language.Rust.Data.Position
import Language.Rust.Quote import Language.Rust.Quote
import Language.Rust.Syntax import Language.Rust.Syntax
import RustModule
import System.Random(RandomGen) import System.Random(RandomGen)
numTestCases :: Int numTestCases :: Int
numTestCases = 3000 numTestCases = 3000
safeScaleOps :: File safeScaleOps :: RustModule
safeScaleOps = File { safeScaleOps = RustModule {
predicate = \ me others -> (me + 64) `elem` others, predicate = \ me others -> (me + 64) `elem` others,
outputName = "safe_scale", outputName = "safe_scale",
isUnsigned = True, isUnsigned = True,
@@ -29,8 +29,8 @@ safeScaleOps = File {
testCase = Just generateSafeTests testCase = Just generateSafeTests
} }
unsafeScaleOps :: File unsafeScaleOps :: RustModule
unsafeScaleOps = File { unsafeScaleOps = RustModule {
predicate = \ _ _ -> True, predicate = \ _ _ -> True,
outputName = "unsafe_scale", outputName = "unsafe_scale",
isUnsigned = True, isUnsigned = True,

View File

@@ -5,20 +5,20 @@ module Shift(shiftOps, signedShiftOps)
import Data.Bits(shiftL,shiftR) import Data.Bits(shiftL,shiftR)
import Data.Map.Strict(Map) import Data.Map.Strict(Map)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import File
import Gen(toLit) import Gen(toLit)
import Generators import Generators
import Language.Rust.Data.Ident import Language.Rust.Data.Ident
import Language.Rust.Data.Position import Language.Rust.Data.Position
import Language.Rust.Quote import Language.Rust.Quote
import Language.Rust.Syntax import Language.Rust.Syntax
import RustModule
import System.Random(RandomGen) import System.Random(RandomGen)
numTestCases :: Int numTestCases :: Int
numTestCases = 3000 numTestCases = 3000
shiftOps :: File shiftOps :: RustModule
shiftOps = File { shiftOps = RustModule {
predicate = \ _ _ -> True, predicate = \ _ _ -> True,
outputName = "shift", outputName = "shift",
isUnsigned = True, isUnsigned = True,
@@ -26,8 +26,8 @@ shiftOps = File {
testCase = Just generateTests testCase = Just generateTests
} }
signedShiftOps :: File signedShiftOps :: RustModule
signedShiftOps = File { signedShiftOps = RustModule {
predicate = \ _ _ -> True, predicate = \ _ _ -> True,
outputName = "sshift", outputName = "sshift",
isUnsigned = False, isUnsigned = False,

View File

@@ -2,15 +2,14 @@
module Signed(signedBaseOps) module Signed(signedBaseOps)
where where
import File
import Language.Rust.Data.Ident import Language.Rust.Data.Ident
import Language.Rust.Data.Position import Language.Rust.Data.Position
import Language.Rust.Quote import Language.Rust.Quote
import Language.Rust.Syntax import Language.Rust.Syntax
import RustModule
signedBaseOps :: RustModule
signedBaseOps :: File signedBaseOps = RustModule {
signedBaseOps = File {
predicate = const (const True), predicate = const (const True),
outputName = "base", outputName = "base",
isUnsigned = False, isUnsigned = False,

View File

@@ -10,20 +10,20 @@ module Subtract(
import Data.Bits((.&.)) import Data.Bits((.&.))
import Data.Map.Strict(Map) import Data.Map.Strict(Map)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import File
import Gen(toLit) import Gen(toLit)
import Generators import Generators
import Language.Rust.Data.Ident import Language.Rust.Data.Ident
import Language.Rust.Data.Position import Language.Rust.Data.Position
import Language.Rust.Quote import Language.Rust.Quote
import Language.Rust.Syntax import Language.Rust.Syntax
import RustModule
import System.Random(RandomGen) import System.Random(RandomGen)
numTestCases :: Int numTestCases :: Int
numTestCases = 3000 numTestCases = 3000
safeSubtractOps :: File safeSubtractOps :: RustModule
safeSubtractOps = File { safeSubtractOps = RustModule {
predicate = \ me others -> (me + 64) `elem` others, predicate = \ me others -> (me + 64) `elem` others,
outputName = "safe_sub", outputName = "safe_sub",
isUnsigned = True, isUnsigned = True,
@@ -31,8 +31,8 @@ safeSubtractOps = File {
testCase = Just generateSafeTests testCase = Just generateSafeTests
} }
safeSignedSubtractOps :: File safeSignedSubtractOps :: RustModule
safeSignedSubtractOps = File { safeSignedSubtractOps = RustModule {
predicate = \ me others -> (me + 64) `elem` others, predicate = \ me others -> (me + 64) `elem` others,
outputName = "safe_ssub", outputName = "safe_ssub",
isUnsigned = False, isUnsigned = False,
@@ -40,8 +40,8 @@ safeSignedSubtractOps = File {
testCase = Just generateSafeSignedTests testCase = Just generateSafeSignedTests
} }
unsafeSubtractOps :: File unsafeSubtractOps :: RustModule
unsafeSubtractOps = File { unsafeSubtractOps = RustModule {
predicate = \ _ _ -> True, predicate = \ _ _ -> True,
outputName = "unsafe_sub", outputName = "unsafe_sub",
isUnsigned = True, isUnsigned = True,
@@ -49,8 +49,8 @@ unsafeSubtractOps = File {
testCase = Just generateUnsafeTests testCase = Just generateUnsafeTests
} }
unsafeSignedSubtractOps :: File unsafeSignedSubtractOps :: RustModule
unsafeSignedSubtractOps = File { unsafeSignedSubtractOps = RustModule {
predicate = \ _ _ -> True, predicate = \ _ _ -> True,
outputName = "unsafe_ssub", outputName = "unsafe_ssub",
isUnsigned = False, isUnsigned = False,