Some commits in the way of cleaning up the Rust and generating module lists.
This commit is contained in:
@@ -17,14 +17,15 @@ extra-source-files: CHANGELOG.md
|
|||||||
|
|
||||||
executable generation
|
executable generation
|
||||||
main-is: Main.hs
|
main-is: Main.hs
|
||||||
other-modules: Base, BinaryOps, Compare, Conversions, CryptoNum, File, Gen
|
other-modules: Base, BinaryOps, Compare, Conversions, CryptoNum, File, Gen, Generators
|
||||||
-- other-extensions:
|
-- other-extensions:
|
||||||
build-depends: base >= 4.12.0.0,
|
build-depends: base >= 4.12.0.0,
|
||||||
containers,
|
containers,
|
||||||
directory,
|
directory,
|
||||||
filepath,
|
filepath,
|
||||||
language-rust,
|
language-rust,
|
||||||
mtl
|
mtl,
|
||||||
|
random
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
ghc-options: -Wall
|
ghc-options: -Wall
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ base :: File
|
|||||||
base = File {
|
base = File {
|
||||||
predicate = \ _ _ -> True,
|
predicate = \ _ _ -> True,
|
||||||
outputName = "base",
|
outputName = "base",
|
||||||
generator = declareBaseStructure
|
isUnsigned = True,
|
||||||
|
generator = declareBaseStructure,
|
||||||
|
testCase = Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
declareBaseStructure :: Word -> SourceFile Span
|
declareBaseStructure :: Word -> SourceFile Span
|
||||||
@@ -86,25 +88,3 @@ buildPrints entries printer = go (entries - 1)
|
|||||||
-- Lit [] (Int Dec (fromIntegral x) Unsuffixed mempty) mempty
|
-- Lit [] (Int Dec (fromIntegral x) Unsuffixed mempty) mempty
|
||||||
cur = [stmt| write!(f, $$(litStr), self.value[$$(curi)])?; |]
|
cur = [stmt| write!(f, $$(litStr), self.value[$$(curi)])?; |]
|
||||||
in cur : rest
|
in cur : rest
|
||||||
|
|
||||||
-- implFor "fmt::UpperHex" name $
|
|
||||||
-- wrapIndent "fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result" $
|
|
||||||
-- do forM_ (reverse [1..top]) $ \ i ->
|
|
||||||
-- out ("write!(f, \"{:X}\", self.value[" ++ show i ++ "])?;")
|
|
||||||
-- out "write!(f, \"{:X}\", self.value[0])"
|
|
||||||
-- blank
|
|
||||||
-- implFor "fmt::LowerHex" name $
|
|
||||||
-- wrapIndent "fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result" $
|
|
||||||
-- do forM_ (reverse [1..top]) $ \ i ->
|
|
||||||
-- out ("write!(f, \"{:x}\", self.value[" ++ show i ++ "])?;")
|
|
||||||
-- out "write!(f, \"{:x}\", self.value[0])"
|
|
||||||
-- blank
|
|
||||||
-- implFor "Arbitrary" name $
|
|
||||||
-- wrapIndent "fn arbitrary<G: Gen>(g: &mut G) -> Self" $
|
|
||||||
-- do out (name ++ " {")
|
|
||||||
-- indent $
|
|
||||||
-- do out ("value: [")
|
|
||||||
-- indent $ forM_ [0..top] $ \ _ ->
|
|
||||||
-- out ("g.next_u64(),")
|
|
||||||
-- out ("]")
|
|
||||||
-- out ("}")
|
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ binaryOps :: File
|
|||||||
binaryOps = File {
|
binaryOps = File {
|
||||||
predicate = \ _ _ -> True,
|
predicate = \ _ _ -> True,
|
||||||
outputName = "binary",
|
outputName = "binary",
|
||||||
generator = declareBinaryOperators
|
isUnsigned = True,
|
||||||
|
generator = declareBinaryOperators,
|
||||||
|
testCase = Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
declareBinaryOperators :: Word -> SourceFile Span
|
declareBinaryOperators :: Word -> SourceFile Span
|
||||||
@@ -81,7 +83,7 @@ declareBinaryOperators bitsize =
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn or_associative(a: $$struct_name, b: $$struct_name, c: $$struct_name) -> bool {
|
fn or_associative(a: $$struct_name, b: $$struct_name, c: $$struct_name) -> bool {
|
||||||
((&a | &b) & &c) == (&a | (&b | &c))
|
((&a | &b) | &c) == (&a | (&b | &c))
|
||||||
}
|
}
|
||||||
fn or_commutative(a: $$struct_name, b: $$struct_name) -> bool {
|
fn or_commutative(a: $$struct_name, b: $$struct_name) -> bool {
|
||||||
(&a | &b) == (&b | &a)
|
(&a | &b) == (&b | &a)
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ comparisons :: File
|
|||||||
comparisons = File {
|
comparisons = File {
|
||||||
predicate = \ _ _ -> True,
|
predicate = \ _ _ -> True,
|
||||||
outputName = "compare",
|
outputName = "compare",
|
||||||
generator = declareComparators
|
isUnsigned = True,
|
||||||
|
generator = declareComparators,
|
||||||
|
testCase = Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
declareComparators :: Word -> SourceFile Span
|
declareComparators :: Word -> SourceFile Span
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ conversions :: File
|
|||||||
conversions = File {
|
conversions = File {
|
||||||
predicate = \ _ _ -> True,
|
predicate = \ _ _ -> True,
|
||||||
outputName = "conversions",
|
outputName = "conversions",
|
||||||
generator = declareConversions
|
isUnsigned = True,
|
||||||
|
generator = declareConversions,
|
||||||
|
testCase = Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
declareConversions :: Word -> SourceFile Span
|
declareConversions :: Word -> SourceFile Span
|
||||||
@@ -26,17 +28,17 @@ declareConversions bitsize =
|
|||||||
u16_prims = buildPrimitives sname (mkIdent "u16") entries
|
u16_prims = buildPrimitives sname (mkIdent "u16") entries
|
||||||
u32_prims = buildPrimitives sname (mkIdent "u32") entries
|
u32_prims = buildPrimitives sname (mkIdent "u32") entries
|
||||||
u64_prims = buildPrimitives sname (mkIdent "u64") entries
|
u64_prims = buildPrimitives sname (mkIdent "u64") entries
|
||||||
|
usz_prims = buildPrimitives sname (mkIdent "usize") entries
|
||||||
u128_prims = generateU128Primitives sname entries
|
u128_prims = generateU128Primitives sname entries
|
||||||
i8_prims = generateSignedPrims sname (mkIdent "u8") (mkIdent "i8")
|
i8_prims = generateSignedPrims sname (mkIdent "u8") (mkIdent "i8")
|
||||||
i16_prims = generateSignedPrims sname (mkIdent "u16") (mkIdent "i16")
|
i16_prims = generateSignedPrims sname (mkIdent "u16") (mkIdent "i16")
|
||||||
i32_prims = generateSignedPrims sname (mkIdent "u32") (mkIdent "i32")
|
i32_prims = generateSignedPrims sname (mkIdent "u32") (mkIdent "i32")
|
||||||
i64_prims = generateSignedPrims sname (mkIdent "u64") (mkIdent "i64")
|
i64_prims = generateSignedPrims sname (mkIdent "u64") (mkIdent "i64")
|
||||||
|
isz_prims = buildPrimitives sname (mkIdent "isize") entries
|
||||||
i128_prims = generateI128Primitives sname
|
i128_prims = generateI128Primitives sname
|
||||||
in [sourceFile|
|
in [sourceFile|
|
||||||
use core::convert::{From,TryFrom};
|
use core::convert::{From,TryFrom};
|
||||||
use crate::CryptoNum;
|
use crate::CryptoNum;
|
||||||
#[cfg(test)]
|
|
||||||
use quickcheck::quickcheck;
|
|
||||||
use super::$$sname;
|
use super::$$sname;
|
||||||
use crate::ConversionError;
|
use crate::ConversionError;
|
||||||
|
|
||||||
@@ -44,12 +46,14 @@ declareConversions bitsize =
|
|||||||
$@{u16_prims}
|
$@{u16_prims}
|
||||||
$@{u32_prims}
|
$@{u32_prims}
|
||||||
$@{u64_prims}
|
$@{u64_prims}
|
||||||
|
$@{usz_prims}
|
||||||
$@{u128_prims}
|
$@{u128_prims}
|
||||||
|
|
||||||
$@{i8_prims}
|
$@{i8_prims}
|
||||||
$@{i16_prims}
|
$@{i16_prims}
|
||||||
$@{i32_prims}
|
$@{i32_prims}
|
||||||
$@{i64_prims}
|
$@{i64_prims}
|
||||||
|
$@{isz_prims}
|
||||||
$@{i128_prims}
|
$@{i128_prims}
|
||||||
|]
|
|]
|
||||||
|
|
||||||
|
|||||||
@@ -4,18 +4,28 @@ module CryptoNum(
|
|||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
|
import Data.Bits(testBit)
|
||||||
|
import Data.Map.Strict(Map)
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
import File
|
import File
|
||||||
import Gen
|
import Gen
|
||||||
|
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 System.Random(RandomGen)
|
||||||
|
|
||||||
|
numTestCases :: Int
|
||||||
|
numTestCases = 3000
|
||||||
|
|
||||||
cryptoNum :: File
|
cryptoNum :: File
|
||||||
cryptoNum = File {
|
cryptoNum = File {
|
||||||
predicate = \ _ _ -> True,
|
predicate = \ _ _ -> True,
|
||||||
outputName = "cryptonum",
|
outputName = "cryptonum",
|
||||||
generator = declareCryptoNumInstance
|
isUnsigned = True,
|
||||||
|
generator = declareCryptoNumInstance,
|
||||||
|
testCase = Just generateTests
|
||||||
}
|
}
|
||||||
|
|
||||||
declareCryptoNumInstance :: Word -> SourceFile Span
|
declareCryptoNumInstance :: Word -> SourceFile Span
|
||||||
@@ -35,6 +45,8 @@ declareCryptoNumInstance bitsize =
|
|||||||
entrieslit = toLit entries
|
entrieslit = toLit entries
|
||||||
in [sourceFile|
|
in [sourceFile|
|
||||||
use core::cmp::min;
|
use core::cmp::min;
|
||||||
|
#[cfg(test)]
|
||||||
|
use core::convert::TryFrom;
|
||||||
use crate::CryptoNum;
|
use crate::CryptoNum;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use crate::testing::{build_test_path,run_test};
|
use crate::testing::{build_test_path,run_test};
|
||||||
@@ -134,6 +146,23 @@ declareCryptoNumInstance bitsize =
|
|||||||
let (neg5, rbytes) = case.get("r").unwrap();
|
let (neg5, rbytes) = case.get("r").unwrap();
|
||||||
let (neg6, bbytes) = case.get("b").unwrap();
|
let (neg6, bbytes) = case.get("b").unwrap();
|
||||||
let (neg7, tbytes) = case.get("t").unwrap();
|
let (neg7, tbytes) = case.get("t").unwrap();
|
||||||
|
|
||||||
|
assert!(!neg0 && !neg1 && !neg2 && !neg3 &&
|
||||||
|
!neg4 && !neg5 && !neg6 && !neg7);
|
||||||
|
let mut x = $$sname::from_bytes(&xbytes);
|
||||||
|
let z = 1 == zbytes[0];
|
||||||
|
let e = 1 == ebytes[0];
|
||||||
|
let o = 1 == obytes[0];
|
||||||
|
let t = 1 == tbytes[0];
|
||||||
|
let m = usize::try_from($$sname::from_bytes(&mbytes)).unwrap();
|
||||||
|
let b = usize::try_from($$sname::from_bytes(&bbytes)).unwrap();
|
||||||
|
let r = $$sname::from_bytes(&rbytes);
|
||||||
|
assert_eq!(x.is_zero(), z);
|
||||||
|
assert_eq!(x.is_even(), e);
|
||||||
|
assert_eq!(x.is_odd(), o);
|
||||||
|
assert_eq!(x.testbit(b), t);
|
||||||
|
x.mask(m);
|
||||||
|
assert_eq!(x, r);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|]
|
|]
|
||||||
@@ -145,3 +174,21 @@ generateZeroTests i entries
|
|||||||
let ilit = toLit i
|
let ilit = toLit i
|
||||||
in [stmt| result &= self.value[$$(ilit)] == 0; |] :
|
in [stmt| result &= self.value[$$(ilit)] == 0; |] :
|
||||||
generateZeroTests (i + 1) entries
|
generateZeroTests (i + 1) entries
|
||||||
|
|
||||||
|
generateTests :: RandomGen g => Word -> g -> [Map String String]
|
||||||
|
generateTests size g = go g numTestCases
|
||||||
|
where
|
||||||
|
go _ 0 = []
|
||||||
|
go g0 i =
|
||||||
|
let (x, g1) = generateNum g0 size
|
||||||
|
(m, g2) = generateNum g1 size
|
||||||
|
(b, g3) = generateNum g2 16
|
||||||
|
m' = m `mod` (fromIntegral size `div` 64)
|
||||||
|
r = m `mod` (2 ^ (64 * m'))
|
||||||
|
t = x `testBit` (fromIntegral b)
|
||||||
|
tcase = Map.fromList [("x", showX x), ("z", showB (x == 0)),
|
||||||
|
("e", showB (even x)), ("o", showB (odd x)),
|
||||||
|
("m", showX m'), ("r", showX r),
|
||||||
|
("b", showX b), ("t", showB t)]
|
||||||
|
in tcase : go g3 (i - 1)
|
||||||
|
|
||||||
|
|||||||
@@ -1,91 +1,129 @@
|
|||||||
{-# LANGUAGE QuasiQuotes #-}
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
|
{-# LANGUAGE RankNTypes #-}
|
||||||
module File(
|
module File(
|
||||||
File(..),
|
File(..),
|
||||||
Task(..),
|
Task(..),
|
||||||
addModuleTasks,
|
generateTasks
|
||||||
makeTask
|
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
|
import Control.Monad(forM_)
|
||||||
import Data.Char(toUpper)
|
import Data.Char(toUpper)
|
||||||
|
import Data.List(isPrefixOf)
|
||||||
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 System.FilePath(takeBaseName,takeDirectory,takeFileName,(</>))
|
import Language.Rust.Data.Ident(mkIdent)
|
||||||
import Language.Rust.Data.Ident(Ident,mkIdent)
|
|
||||||
import Language.Rust.Data.Position(Span)
|
import Language.Rust.Data.Position(Span)
|
||||||
|
import Language.Rust.Pretty(writeSourceFile)
|
||||||
import Language.Rust.Quote(item,sourceFile)
|
import Language.Rust.Quote(item,sourceFile)
|
||||||
import Language.Rust.Syntax(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 {
|
data File = File {
|
||||||
predicate :: Word -> [Word] -> Bool,
|
predicate :: Word -> [Word] -> Bool,
|
||||||
outputName :: FilePath,
|
outputName :: FilePath,
|
||||||
generator :: Word -> SourceFile Span
|
isUnsigned :: Bool,
|
||||||
|
generator :: Word -> SourceFile Span,
|
||||||
|
testCase :: forall g. RandomGen g => Maybe (Word -> g -> [Map String String])
|
||||||
}
|
}
|
||||||
|
|
||||||
data Task = Task {
|
data Task = Task {
|
||||||
outputFile :: FilePath,
|
outputFile :: FilePath,
|
||||||
fileData :: SourceFile Span
|
writer :: Handle -> IO ()
|
||||||
}
|
}
|
||||||
|
|
||||||
makeTask :: FilePath ->
|
show5 :: Word -> String
|
||||||
Word -> [Word] ->
|
show5 = go . show
|
||||||
File ->
|
|
||||||
Maybe Task
|
|
||||||
makeTask base size allSizes file
|
|
||||||
| predicate file size allSizes =
|
|
||||||
Just Task {
|
|
||||||
outputFile = base </> ("u" ++ show size) </> outputName file <> ".rs",
|
|
||||||
fileData = generator file size
|
|
||||||
}
|
|
||||||
| otherwise =
|
|
||||||
Nothing
|
|
||||||
|
|
||||||
addModuleTasks :: FilePath -> [Task] -> [Task]
|
|
||||||
addModuleTasks base baseTasks = unsignedTask : (baseTasks ++ moduleTasks)
|
|
||||||
where
|
where
|
||||||
moduleMap :: Map String [String]
|
go x | length x < 5 = go ('0' : x)
|
||||||
moduleMap = foldr addModuleInfo Map.empty baseTasks
|
| otherwise = x
|
||||||
|
|
||||||
addModuleInfo :: Task -> Map String [String] -> Map String [String]
|
generateTasks :: RandomGen g => g -> [File] -> [Word] -> [Task]
|
||||||
addModuleInfo task =
|
generateTasks rng files sizes = basicTasks ++ moduleTasks
|
||||||
Map.insertWith (++) (takeDirectory (outputFile task))
|
where
|
||||||
[takeBaseName (outputFile task)]
|
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 = if isUnsigned file then "unsigned" else "signed"
|
||||||
|
mainTask = Task {
|
||||||
|
outputFile = "src" </> signedBit </> ("u" ++ show size) </>
|
||||||
|
outputName file ++ ".rs",
|
||||||
|
writer = \ hndl -> writeSourceFile hndl (generator file size)
|
||||||
|
}
|
||||||
|
in case testCase file of
|
||||||
|
Nothing ->
|
||||||
|
mainTask : tasks
|
||||||
|
Just caseGenerator ->
|
||||||
|
let testTask = Task {
|
||||||
|
outputFile = "testdata" </> outputName file </>
|
||||||
|
("U" ++ show5 size ++ ".test"),
|
||||||
|
writer = \ hndl -> writeTestCase hndl (caseGenerator size myg)
|
||||||
|
}
|
||||||
|
in testTask : mainTask : tasks
|
||||||
|
|
||||||
moduleTasks :: [Task]
|
generateModules :: [Task] -> [Task]
|
||||||
moduleTasks = Map.foldrWithKey generateModuleTask [] moduleMap
|
generateModules tasks = Map.foldrWithKey maddModule [] fileMap ++ [unsignedTask]
|
||||||
|
where
|
||||||
generateModuleTask :: String -> [String] -> [Task] -> [Task]
|
maddModule path mods acc
|
||||||
generateModuleTask directory mods acc = acc ++ [Task {
|
| "src/unsigned" `isPrefixOf` path =
|
||||||
outputFile = directory </> "mod.rs",
|
let (basePath, lowerName) = splitFileName (init path)
|
||||||
fileData =
|
upperName = map toUpper lowerName
|
||||||
let modules = map (buildModule . mkIdent) mods
|
task = Task {
|
||||||
user = mkIdent (upcase (takeFileName directory))
|
outputFile = basePath </> lowerName ++ ".rs",
|
||||||
in [sourceFile|
|
writer = \ hndl ->
|
||||||
$@{modules}
|
do forM_ mods $ \ modl ->
|
||||||
pub use base::$$user;
|
hPutStrLn hndl ("mod " ++ modl ++ ";")
|
||||||
|]
|
hPutStrLn hndl ("pub use base::" ++ upperName ++ ";")
|
||||||
}]
|
}
|
||||||
|
in task : acc
|
||||||
unsignedTask :: Task
|
| otherwise =
|
||||||
unsignedTask = Task {
|
acc
|
||||||
outputFile = base </> "unsigned" </> "mod.rs",
|
fileMap = foldr buildBaseMap Map.empty tasks
|
||||||
fileData =
|
buildBaseMap task acc =
|
||||||
let modules = map (buildModule . mkIdent . takeFileName) (Map.keys moduleMap)
|
let (dir, fileext) = splitFileName (outputFile task)
|
||||||
uses = map (buildUse . takeFileName) (Map.keys moduleMap)
|
file = dropExtension fileext
|
||||||
in [sourceFile|
|
in Map.insertWith (++) dir [file] acc
|
||||||
$@{modules}
|
--
|
||||||
$@{uses}
|
unsignedTask =
|
||||||
|
let mods = Map.foldrWithKey topModule [] fileMap
|
||||||
|
pubuses = Map.foldrWithKey pubUse [] fileMap
|
||||||
|
in Task {
|
||||||
|
outputFile = "src" </> "unsigned.rs",
|
||||||
|
writer = \ hndl ->
|
||||||
|
writeSourceFile hndl [sourceFile|
|
||||||
|
$@{mods}
|
||||||
|
$@{pubuses}
|
||||||
|]
|
|]
|
||||||
}
|
}
|
||||||
|
topModule path _ acc
|
||||||
|
| "src/unsigned" `isPrefixOf` path =
|
||||||
|
let lowerName = takeFileName (init path)
|
||||||
|
modl = mkIdent lowerName
|
||||||
|
in [item| mod $$modl; |] : acc
|
||||||
|
| otherwise =
|
||||||
|
acc
|
||||||
|
pubUse path _ acc
|
||||||
|
| "src/unsigned" `isPrefixOf` path =
|
||||||
|
let lowerName = takeFileName (init path)
|
||||||
|
tname = mkIdent (map toUpper lowerName)
|
||||||
|
modl = mkIdent lowerName
|
||||||
|
in [item| pub use $$modl::$$tname; |] : acc
|
||||||
|
| otherwise =
|
||||||
|
acc
|
||||||
|
|
||||||
buildModule :: Ident -> Item Span
|
|
||||||
buildModule x = [item| mod $$x; |]
|
|
||||||
|
|
||||||
buildUse :: String -> Item Span
|
writeTestCase :: Handle -> [Map String String] -> IO ()
|
||||||
buildUse x =
|
writeTestCase hndl tests =
|
||||||
let base = mkIdent x
|
forM_ tests $ \ test ->
|
||||||
up = mkIdent (upcase x)
|
forM_ (Map.toList test) $ \ (key, value) ->
|
||||||
in [item| pub use $$base::$$up; |]
|
hPutStrLn hndl (key ++ ": " ++ value)
|
||||||
|
|
||||||
upcase :: String -> String
|
|
||||||
upcase = map toUpper
|
|
||||||
|
|||||||
19
generation/src/Generators.hs
Normal file
19
generation/src/Generators.hs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
module Generators
|
||||||
|
where
|
||||||
|
|
||||||
|
import Numeric(showHex)
|
||||||
|
import System.Random(RandomGen,random)
|
||||||
|
|
||||||
|
generateNum :: RandomGen g => g -> Word -> (Integer, g)
|
||||||
|
generateNum g size =
|
||||||
|
let (x, g') = random g
|
||||||
|
x' = x `mod` (2 ^ size)
|
||||||
|
in (x', g')
|
||||||
|
|
||||||
|
showX :: Integer -> String
|
||||||
|
showX x | x < 0 = "-" ++ showX (abs x)
|
||||||
|
| otherwise = showHex x ""
|
||||||
|
|
||||||
|
showB :: Bool -> String
|
||||||
|
showB False = "0"
|
||||||
|
showB True = "1"
|
||||||
@@ -7,14 +7,13 @@ import Compare(comparisons)
|
|||||||
import Conversions(conversions)
|
import Conversions(conversions)
|
||||||
import CryptoNum(cryptoNum)
|
import CryptoNum(cryptoNum)
|
||||||
import Control.Monad(forM_,unless)
|
import Control.Monad(forM_,unless)
|
||||||
import Data.Maybe(mapMaybe)
|
import File(File,Task(..),generateTasks)
|
||||||
import File(File,Task(..),addModuleTasks,makeTask)
|
|
||||||
import Language.Rust.Pretty(writeSourceFile)
|
|
||||||
import System.Directory(createDirectoryIfMissing)
|
import System.Directory(createDirectoryIfMissing)
|
||||||
import System.Environment(getArgs)
|
import System.Environment(getArgs)
|
||||||
import System.Exit(die)
|
import System.Exit(die)
|
||||||
import System.FilePath(takeDirectory,(</>))
|
import System.FilePath(takeDirectory,(</>))
|
||||||
import System.IO(IOMode(..),hPutStrLn,withFile)
|
import System.IO(IOMode(..),withFile)
|
||||||
|
import System.Random(getStdGen)
|
||||||
|
|
||||||
lowestBitsize :: Word
|
lowestBitsize :: Word
|
||||||
lowestBitsize = 192
|
lowestBitsize = 192
|
||||||
@@ -38,26 +37,20 @@ signedFiles :: [File]
|
|||||||
signedFiles = [
|
signedFiles = [
|
||||||
]
|
]
|
||||||
|
|
||||||
makeTasks :: FilePath -> [File] -> [Task]
|
allFiles :: [File]
|
||||||
makeTasks basePath files =
|
allFiles = unsignedFiles ++ signedFiles
|
||||||
concatMap (\ sz -> mapMaybe (makeTask basePath sz bitsizes) files) bitsizes
|
|
||||||
|
|
||||||
makeAllTasks :: FilePath -> [Task]
|
|
||||||
makeAllTasks basePath = addModuleTasks basePath $
|
|
||||||
makeTasks (basePath </> "unsigned") unsignedFiles ++
|
|
||||||
makeTasks (basePath </> "signed") signedFiles
|
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main =
|
main =
|
||||||
do args <- getArgs
|
do args <- getArgs
|
||||||
unless (length args == 1) $
|
unless (length args == 1) $
|
||||||
die ("generation takes exactly one argument, the target directory")
|
die ("generation takes exactly one argument, the target directory")
|
||||||
let tasks = makeAllTasks (head args)
|
g <- getStdGen
|
||||||
total = length tasks
|
let allTasks = generateTasks g allFiles bitsizes
|
||||||
forM_ (zip [(1::Word)..] tasks) $ \ (i, task) ->
|
total = length allTasks
|
||||||
|
forM_ (zip [(1::Word)..] allTasks) $ \ (i, task) ->
|
||||||
do putStrLn ("[" ++ show i ++ "/" ++ show total ++ "] " ++ outputFile task)
|
do putStrLn ("[" ++ show i ++ "/" ++ show total ++ "] " ++ outputFile task)
|
||||||
createDirectoryIfMissing True (takeDirectory (outputFile task))
|
let target = head args </> outputFile task
|
||||||
withFile (outputFile task) WriteMode $ \ targetHandle ->
|
createDirectoryIfMissing True (takeDirectory target)
|
||||||
do hPutStrLn targetHandle
|
withFile target WriteMode $ \ targetHandle ->
|
||||||
"// WARNING: This file was automatically generated. Do not edit!"
|
writer task targetHandle
|
||||||
writeSourceFile targetHandle (fileData task)
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ pub trait CryptoNum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An error in conversion of large numbers (either to primitives or to other numbers
|
/// An error in conversion of large numbers (either to primitives or to other numbers
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum ConversionError {
|
pub enum ConversionError {
|
||||||
NegativeToUnsigned,
|
NegativeToUnsigned,
|
||||||
Overflow
|
Overflow
|
||||||
|
|||||||
0
src/signed.rs
Normal file
0
src/signed.rs
Normal file
Reference in New Issue
Block a user