Support generating signed numbers.

This commit is contained in:
2020-01-14 12:13:40 -10:00
parent 4383b67c44
commit e46cfe56d1
15 changed files with 218 additions and 30 deletions

View File

@@ -14,6 +14,7 @@ import ModOps(modulusOps)
import Multiply(safeMultiplyOps, unsafeMultiplyOps)
import Scale(safeScaleOps, unsafeScaleOps)
import Shift(shiftOps)
import Signed(signedBaseOps)
import Subtract(safeSubtractOps,unsafeSubtractOps)
import System.Directory(createDirectoryIfMissing)
import System.Environment(getArgs)
@@ -53,6 +54,7 @@ unsignedFiles = [
signedFiles :: [File]
signedFiles = [
signedBaseOps
]
allFiles :: [File]

View File

@@ -45,6 +45,7 @@ library
Multiply,
Scale,
Shift,
Signed,
Subtract
executable generation

View File

@@ -43,7 +43,7 @@ declareSafeAddOperators bitsize _ =
let sname = mkIdent ("U" ++ show bitsize)
dname = mkIdent ("U" ++ show (bitsize + 64))
fullRippleAdd = makeRippleAdder True (bitsize `div` 64) "res"
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty
testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile|
use core::ops::Add;
use crate::CryptoNum;
@@ -119,7 +119,7 @@ declareUnsafeAddOperators :: Word -> [Word] -> SourceFile Span
declareUnsafeAddOperators bitsize _ =
let sname = mkIdent ("U" ++ show bitsize)
fullRippleAdd = makeRippleAdder False (bitsize `div` 64) "self"
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty
testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile|
use core::ops::AddAssign;
#[cfg(test)]

View File

@@ -4,7 +4,6 @@ module Base(
)
where
-- This is a comment
import File
import Language.Rust.Data.Ident
import Language.Rust.Data.Position

View File

@@ -37,7 +37,7 @@ declareBinaryOperators bitsize _ =
xorOps = generateBinOps "BitXor" struct_name "bitxor" BitXorOp entries
baseNegationStmts = negationStatements "self" entries
refNegationStmts = negationStatements "output" entries
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty
testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile|
use core::ops::{BitAnd,BitAndAssign};
use core::ops::{BitOr,BitOrAssign};

View File

@@ -30,7 +30,7 @@ declareComparators bitsize _ =
entries = bitsize `div` 64
eqStatements = buildEqStatements 0 entries
compareExp = buildCompareExp 0 entries
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty
testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile|
use core::cmp::{Eq,Ordering,PartialEq};
#[cfg(test)]

View File

@@ -43,7 +43,7 @@ declareCryptoNumInstance bitsize _ =
Tree (Token mempty (LiteralTok (IntegerTok (show bytelen)) Nothing))
])
entrieslit = toLit entries
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty
testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile|
use core::cmp::min;
#[cfg(test)]

View File

@@ -30,7 +30,7 @@ declareDivision size _ =
let sname = mkIdent ("U" ++ show size)
entries = size `div` 64
copyAssign = map doCopy [0..entries-1]
testFileLit = Lit [] (Str (testFile size) Cooked Unsuffixed mempty) mempty
testFileLit = Lit [] (Str (testFile True size) Cooked Unsuffixed mempty) mempty
in [sourceFile|
use core::ops::{Div, DivAssign};
use core::ops::{Rem, RemAssign};

View File

@@ -35,8 +35,9 @@ data Task = Task {
writer :: Handle -> IO ()
}
testFile :: Word -> FilePath
testFile size = "U" ++ show5 size ++ ".test"
testFile :: Bool -> Word -> FilePath
testFile True size = "U" ++ show5 size ++ ".test"
testFile False size = "I" ++ show5 size ++ ".test"
show5 :: Word -> String
show5 = go . show
@@ -58,9 +59,10 @@ generateTasks rng files sizes = basicTasks ++ moduleTasks
| otherwise =
let (myg, theirg) = split g
tasks = go theirg files' rest
signedBit = if isUnsigned file then "unsigned" else "signed"
(signedBit, prefix) | isUnsigned file = ("unsigned", "u")
| otherwise = ("signed", "i")
mainTask = Task {
outputFile = "src" </> signedBit </> ("u" ++ show size) </>
outputFile = "src" </> signedBit </> (prefix ++ show size) </>
outputName file ++ ".rs",
writer = \ hndl -> writeSourceFile hndl (generator file size sizes)
}
@@ -69,16 +71,16 @@ generateTasks rng files sizes = basicTasks ++ moduleTasks
mainTask : tasks
Just caseGenerator ->
let testTask = Task {
outputFile = "testdata" </> outputName file </> testFile size,
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 ++ [unsignedTask]
generateModules tasks = Map.foldrWithKey maddModule [] fileMap ++ [signedTask, unsignedTask]
where
maddModule path mods acc
| "src/unsigned" `isPrefixOf` path =
| ("src/unsigned" `isPrefixOf` path) || ("src/signed" `isPrefixOf` path) =
let (basePath, lowerName) = splitFileName (init path)
upperName = map toUpper lowerName
task = Task {
@@ -97,26 +99,28 @@ generateModules tasks = Map.foldrWithKey maddModule [] fileMap ++ [unsignedTask]
file = dropExtension fileext
in Map.insertWith (++) dir [file] acc
--
unsignedTask =
let mods = Map.foldrWithKey topModule [] fileMap
pubuses = Map.foldrWithKey pubUse [] fileMap
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" </> "unsigned.rs",
outputFile = "src" </> (kind ++ ".rs"),
writer = \ hndl ->
writeSourceFile hndl [sourceFile|
$@{mods}
$@{pubuses}
|]
}
topModule path _ acc
| "src/unsigned" `isPrefixOf` path =
topModule kind path _ acc
| ("src/" ++ kind) `isPrefixOf` path =
let lowerName = takeFileName (init path)
modl = mkIdent lowerName
in [item| mod $$modl; |] : acc
| otherwise =
acc
pubUse path _ acc
| "src/unsigned" `isPrefixOf` path =
pubUse kind path _ acc
| ("src/" ++ kind) `isPrefixOf` path =
let lowerName = takeFileName (init path)
tname = mkIdent (map toUpper lowerName)
modl = mkIdent lowerName

View File

@@ -29,7 +29,7 @@ declareModOps :: Word -> [Word] -> SourceFile Span
declareModOps bitsize _ =
let sname = mkIdent ("U" ++ show bitsize)
bname = mkIdent ("U" ++ show (bitsize * 2))
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty
testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile|
use core::convert::TryFrom;
use crate::unsigned::{$$sname, $$bname};

View File

@@ -45,7 +45,7 @@ declareSafeMulOperators bitsize _ =
let sname = mkIdent ("U" ++ show bitsize)
dname = mkIdent ("U" ++ show (bitsize * 2))
fullRippleMul = generateMultiplier True (bitsize `div` 64) "rhs" "res"
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty
testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile|
use core::ops::Mul;
use crate::CryptoNum;
@@ -121,7 +121,7 @@ declareUnsafeMulOperators :: Word -> [Word] -> SourceFile Span
declareUnsafeMulOperators bitsize _ =
let sname = mkIdent ("U" ++ show bitsize)
halfRippleMul = generateMultiplier False (bitsize `div` 64) "rhs" "self"
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty
testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile|
use core::ops::MulAssign;
#[cfg(test)]

View File

@@ -43,7 +43,7 @@ declareSafeScaleOperators bitsize _ =
let sname = mkIdent ("U" ++ show bitsize)
dname = mkIdent ("U" ++ show (bitsize + 64))
fullRippleScale = generateScaletiplier True (bitsize `div` 64) "rhs" "res"
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty
testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile|
use core::ops::Mul;
use crate::CryptoNum;
@@ -158,7 +158,7 @@ declareUnsafeScaleOperators :: Word -> [Word] -> SourceFile Span
declareUnsafeScaleOperators bitsize _ =
let sname = mkIdent ("U" ++ show bitsize)
halfRippleScale = generateScaletiplier False (bitsize `div` 64) "rhs" "self"
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty
testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile|
use core::ops::MulAssign;
#[cfg(test)]

View File

@@ -35,7 +35,7 @@ declareShiftOperators bitsize _ =
shlActualImpl = concatMap actualShlImplLines [1..entries-1]
shrActualImpl = concatMap (actualShrImplLines entries) (reverse [0..entries-1])
resAssign = map reassignSelf [0..entries-1]
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty
testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile|
#[cfg(test)]
use core::convert::TryFrom;

182
generation/src/Signed.hs Normal file
View File

@@ -0,0 +1,182 @@
{-# LANGUAGE QuasiQuotes #-}
module Signed(signedBaseOps)
where
import File
import Language.Rust.Data.Ident
import Language.Rust.Data.Position
import Language.Rust.Quote
import Language.Rust.Syntax
signedBaseOps :: File
signedBaseOps = File {
predicate = const (const True),
outputName = "base",
isUnsigned = False,
generator = declareSigned,
testCase = Nothing
}
declareSigned :: Word -> [Word] -> SourceFile Span
declareSigned bitsize _ =
let sname = mkIdent ("I" ++ show bitsize)
uname = mkIdent ("U" ++ show bitsize)
in [sourceFile|
use core::fmt;
use core::ops::{Neg, Not};
use crate::CryptoNum;
use crate::unsigned::$$uname;
use quickcheck::{Arbitrary,Gen};
#[cfg(test)]
use quickcheck::quickcheck;
#[derive(Clone)]
pub struct $$sname {
contents: $$uname,
}
impl Neg for $$sname {
type Output = $$sname;
fn neg(mut self) -> $$sname {
for x in self.contents.value.iter_mut() {
*x = !*x;
}
let one = $$uname::from(1u64);
self.contents += one;
self
}
}
impl<'a> Neg for &'a $$sname {
type Output = $$sname;
fn neg(self) -> $$sname {
let res = self.clone();
res.neg()
}
}
impl Not for $$sname {
type Output = $$sname;
fn not(mut self) -> $$sname {
for x in self.contents.value.iter_mut() {
*x = !*x;
}
self
}
}
impl<'a> Not for &'a $$sname {
type Output = $$sname;
fn not(self) -> $$sname {
self.clone().not()
}
}
impl fmt::Debug for $$sname {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.contents)
}
}
impl fmt::UpperHex for $$sname {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut temp = self.clone();
if temp.contents.value[temp.contents.value.len()-1] >> 63 == 1 {
write!(f, "-")?;
temp = !temp;
}
write!(f, "{:X}", temp.contents)
}
}
impl fmt::LowerHex for $$sname {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut temp = self.clone();
if temp.contents.value[temp.contents.value.len()-1] >> 63 == 1 {
write!(f, "-")?;
temp = !temp;
}
write!(f, "{:x}", temp.contents)
}
}
impl PartialEq for $$sname {
fn eq(&self, other: &$$sname) -> bool {
let mut all_equal = true;
for (l, r) in self.contents.value.iter().zip(other.contents.value.iter()) {
all_equal &= *l == *r;
}
all_equal
}
}
impl Eq for $$sname { }
impl Arbitrary for $$sname {
fn arbitrary<G: Gen>(g: &mut G) -> $$sname {
$$sname{
contents: $$uname::arbitrary(g),
}
}
}
impl CryptoNum for $$sname {
fn zero() -> $$sname {
$$sname{ contents: $$uname::zero() }
}
fn is_zero(&self) -> bool {
self.contents.is_zero()
}
fn is_even(&self) -> bool {
self.contents.is_even()
}
fn is_odd(&self) -> bool {
self.contents.is_odd()
}
fn bit_length() -> usize {
$$uname::bit_length()
}
fn mask(&mut self, len: usize) {
self.contents.mask(len);
}
fn testbit(&self, bit: usize) -> bool {
self.contents.testbit(bit)
}
fn from_bytes(bytes: &[u8]) -> $$sname {
$$sname{ contents: $$uname::from_bytes(bytes) }
}
fn to_bytes(&self, bytes: &mut [u8]) {
self.contents.to_bytes(bytes);
}
}
#[cfg(test)]
quickcheck! {
fn equality_reflexive(x: $$sname) -> bool {
&x == &x
}
fn equality_symmetric(x: $$sname, y: $$sname) -> bool {
(&x == &y) == (&y == &x)
}
fn double_not(x: $$sname) -> bool {
x == !!&x
}
fn double_neg(x: $$sname) -> bool {
x == --&x
}
}
|]

View File

@@ -43,7 +43,7 @@ declareSafeSubtractOperators bitsize _ =
let sname = mkIdent ("U" ++ show bitsize)
dname = mkIdent ("U" ++ show (bitsize + 64))
fullRippleSubtract = makeRippleSubtracter True (bitsize `div` 64) "res"
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty
testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile|
use core::ops::Sub;
use crate::CryptoNum;
@@ -110,7 +110,7 @@ declareUnsafeSubtractOperators :: Word -> [Word] -> SourceFile Span
declareUnsafeSubtractOperators bitsize _ =
let sname = mkIdent ("U" ++ show bitsize)
fullRippleSubtract = makeRippleSubtracter False (bitsize `div` 64) "self"
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty
testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile|
use core::ops::SubAssign;
#[cfg(test)]