The basic binary operations.

This commit is contained in:
2019-07-15 21:00:12 -07:00
parent fa872c951a
commit ab465296f2
3 changed files with 108 additions and 12 deletions

View File

@@ -7,6 +7,9 @@ module Gen(
blank, blank,
out, out,
wrapIndent, wrapIndent,
implFor,
implFor',
implFor'',
) )
where where
@@ -71,3 +74,15 @@ wrapIndent val middle =
tell (replicate (fromIntegral (indentAmount gs)) ' ') tell (replicate (fromIntegral (indentAmount gs)) ' ')
tell "}\n" tell "}\n"
return res return res
implFor :: String -> String -> Gen a -> Gen a
implFor trait name middle =
wrapIndent ("impl " ++ trait ++ " for " ++ name) middle
implFor' :: String -> String -> Gen a -> Gen a
implFor' trait name middle =
wrapIndent ("impl<'a> " ++ trait ++ " for " ++ name) middle
implFor'' :: String -> String -> Gen a -> Gen a
implFor'' trait name middle =
wrapIndent ("impl<'a,'b> " ++ trait ++ " for " ++ name) middle

View File

@@ -11,7 +11,7 @@ import System.Directory(createDirectoryIfMissing)
import System.Environment(getArgs) import System.Environment(getArgs)
import System.Exit(die) import System.Exit(die)
import System.FilePath((</>)) import System.FilePath((</>))
import UnsignedBase(declareBaseStructure) import UnsignedBase(declareBaseStructure,declareBinaryOperators)
gatherRequirements :: [Requirement] -> Map Int [Operation] gatherRequirements :: [Requirement] -> Map Int [Operation]
gatherRequirements = foldr process Map.empty gatherRequirements = foldr process Map.empty
@@ -29,4 +29,5 @@ main =
createDirectoryIfMissing True basedir createDirectoryIfMissing True basedir
forM_ reqs $ \ (x, ops) -> forM_ reqs $ \ (x, ops) ->
do runGen (basedir </> "mod.rs") (declareBaseStructure size ops) do runGen (basedir </> "mod.rs") (declareBaseStructure size ops)
runGen (basedir </> "binary.rs") (declareBinaryOperators size)

View File

@@ -1,5 +1,6 @@
module UnsignedBase( module UnsignedBase(
declareBaseStructure declareBaseStructure
, declareBinaryOperators
) )
where where
@@ -16,12 +17,13 @@ declareBaseStructure bitsize ops =
out "use core::fmt;" out "use core::fmt;"
out "use super::super::CryptoNum;" out "use super::super::CryptoNum;"
blank blank
out "mod binary_ops;" out "mod binary;"
blank blank
out "#[derive(Clone)]"
wrapIndent ("pub struct " ++ name) $ wrapIndent ("pub struct " ++ name) $
out ("value: [u64; " ++ show entries ++ "]") out ("value: [u64; " ++ show entries ++ "]")
blank blank
wrapIndent ("impl CryptoNum for " ++ name) $ implFor "CryptoNum" name $
do wrapIndent ("fn zero() -> Self") $ do wrapIndent ("fn zero() -> Self") $
out (name ++ "{ value: [0; " ++ show entries ++ "] }") out (name ++ "{ value: [0; " ++ show entries ++ "] }")
blank blank
@@ -51,39 +53,117 @@ declareBaseStructure bitsize ops =
out "return false;" out "return false;"
out "(self.value[idx] & (1u64 << offset)) != 0" out "(self.value[idx] & (1u64 << offset)) != 0"
blank blank
wrapIndent ("impl PartialEq for " ++ name) $ implFor "PartialEq" name $
wrapIndent "fn eq(&self, other: &Self) -> bool" $ wrapIndent "fn eq(&self, other: &Self) -> bool" $
do forM_ (reverse [1..top]) $ \ i -> do forM_ (reverse [1..top]) $ \ i ->
out ("self.value[" ++ show i ++ "] == other.value[" ++ show i ++ "] && ") out ("self.value[" ++ show i ++ "] == other.value[" ++ show i ++ "] && ")
out "self.value[0] == other.value[0]" out "self.value[0] == other.value[0]"
blank blank
out ("impl Eq for " ++ name ++ " {}") implFor "Eq" name $ return ()
blank blank
wrapIndent ("impl Ord for " ++ name) $ implFor "Ord" name $
wrapIndent "fn cmp(&self, other: &Self) -> Ordering" $ wrapIndent "fn cmp(&self, other: &Self) -> Ordering" $
do out ("self.value[" ++ show top ++ "].cmp(&other.value[" ++ show top ++ "])") do out ("self.value[" ++ show top ++ "].cmp(&other.value[" ++ show top ++ "])")
forM_ (reverse [0..top-1]) $ \ i -> forM_ (reverse [0..top-1]) $ \ i ->
out (" .then(self.value[" ++ show i ++ "].cmp(&other.value[" ++ show i ++ "]))") out (" .then(self.value[" ++ show i ++ "].cmp(&other.value[" ++ show i ++ "]))")
blank blank
wrapIndent ("impl PartialOrd for " ++ name) $ implFor "PartialOrd" name $
wrapIndent "fn partial_cmp(&self, other: &Self) -> Option<Ordering>" $ wrapIndent "fn partial_cmp(&self, other: &Self) -> Option<Ordering>" $
out "Some(self.cmp(other))" out "Some(self.cmp(other))"
blank blank
wrapIndent ("impl fmt::Debug for " ++ name) $ implFor "fmt::Debug" name $
wrapIndent "fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result" $ wrapIndent "fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result" $
do out ("f.debug_tuple(" ++ show name ++ ")") do out ("f.debug_tuple(" ++ show name ++ ")")
forM_ [0..top] $ \ i -> forM_ [0..top] $ \ i ->
out (" .field(&self.value[" ++ show i ++ "])") out (" .field(&self.value[" ++ show i ++ "])")
out " .finish()" out " .finish()"
blank blank
wrapIndent ("impl fmt::UpperHex for " ++ name) $ implFor "fmt::UpperHex" name $
wrapIndent "fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result" $ wrapIndent "fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result" $
do forM_ (reverse [1..top]) $ \ i -> do forM_ (reverse [1..top]) $ \ i ->
out ("write!(f, \"{:X}\", self.value[" ++ show i ++ "])?;") out ("write!(f, \"{:X}\", self.value[" ++ show i ++ "])?;")
out "write!(f, \"{:X}\", self.value[0])" out "write!(f, \"{:X}\", self.value[0])"
blank blank
wrapIndent ("impl fmt::LowerHex for " ++ name) $ implFor "fmt::LowerHex" name $
wrapIndent "fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result" $ wrapIndent "fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result" $
do forM_ (reverse [1..top]) $ \ i -> do forM_ (reverse [1..top]) $ \ i ->
out ("write!(f, \"{:x}\", self.value[" ++ show i ++ "])?;") out ("write!(f, \"{:x}\", self.value[" ++ show i ++ "])?;")
out "write!(f, \"{:x}\", self.value[0])" out "write!(f, \"{:x}\", self.value[0])"
declareBinaryOperators :: Int -> Gen ()
declareBinaryOperators bitsize =
do let name = "U" ++ show bitsize
entries = bitsize `div` 64
out "use core::ops::{BitAnd,BitAndAssign};"
out "use core::ops::{BitOr,BitOrAssign};"
out "use core::ops::{BitXor,BitXorAssign};"
out "use core::ops::Not;"
out ("use super::U" ++ show bitsize ++ ";")
blank
generateBinOps "BitAnd" name "bitand" "&=" entries
blank
generateBinOps "BitOr" name "bitor" "|=" entries
blank
generateBinOps "BitXor" name "bitxor" "^=" entries
blank
implFor "Not" name $
do out "type Output = Self;"
blank
wrapIndent "fn not(mut self) -> Self" $
do forM_ [0..entries-1] $ \ i ->
out ("self.value[" ++ show i ++ "] = !self.value[" ++ show i ++ "];")
out "self"
blank
implFor' "Not" ("&'a " ++ name) $
do out ("type Output = " ++ name ++ ";")
blank
wrapIndent ("fn not(self) -> " ++ name) $
do out "let mut output = self.clone();"
forM_ [0..entries-1] $ \ i ->
out ("output.value[" ++ show i ++ "] = !self.value[" ++ show i ++ "];")
out "output"
generateBinOps :: String -> String -> String -> String -> Int -> Gen ()
generateBinOps trait name fun op entries =
do implFor (trait ++ "Assign") name $
wrapIndent ("fn " ++ fun ++ "_assign(&mut self, rhs: Self)") $
forM_ [0..entries-1] $ \ i ->
out ("self.value[" ++ show i ++ "] "++op++" rhs.value[" ++ show i ++ "];")
blank
implFor' (trait ++ "Assign<&'a " ++ name ++ ">") name $
wrapIndent ("fn " ++ fun ++ "_assign(&mut self, rhs: &Self)") $
forM_ [0..entries-1] $ \ i ->
out ("self.value[" ++ show i ++ "] "++op++" rhs.value[" ++ show i ++ "];")
blank
generateBinOpsFromAssigns trait name fun op
generateBinOpsFromAssigns :: String -> String -> String -> String -> Gen ()
generateBinOpsFromAssigns trait name fun op =
do implFor trait name $
do out "type Output = Self;"
blank
wrapIndent ("fn " ++ fun ++ "(mut self, rhs: Self) -> Self") $
do out ("self " ++ op ++ " rhs;")
out "self"
blank
implFor' (trait ++ "<&'a " ++ name ++ ">") name $
do out "type Output = Self;"
blank
wrapIndent ("fn " ++ fun ++ "(mut self, rhs: &Self) -> Self") $
do out ("self " ++ op ++ " rhs;")
out "self"
blank
implFor' (trait ++ "<" ++ name ++ ">") ("&'a " ++ name) $
do out ("type Output = " ++ name ++ ";")
blank
wrapIndent ("fn " ++ fun ++ "(self, mut rhs: " ++ name ++ ") -> " ++ name) $
do out ("rhs " ++ op ++ " self;")
out "rhs"
blank
implFor'' (trait ++ "<&'a " ++ name ++ ">") ("&'b " ++ name) $
do out ("type Output = " ++ name ++ ";")
blank
wrapIndent ("fn " ++ fun ++ "(self, rhs: &" ++ name ++ ") -> " ++ name) $
do out "let mut output = self.clone();"
out ("output " ++ op ++ " rhs;")
out "output"