Start working on switching to language-rust as a generator, for fun.
This commit is contained in:
@@ -1,9 +1,14 @@
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
module Compare(comparisons)
|
||||
where
|
||||
|
||||
import Control.Monad(forM_)
|
||||
import File
|
||||
import Gen
|
||||
import Language.Rust.Data.Ident
|
||||
import Language.Rust.Data.Position
|
||||
import Language.Rust.Quote
|
||||
import Language.Rust.Pretty
|
||||
import Language.Rust.Syntax
|
||||
|
||||
comparisons :: File
|
||||
comparisons = File {
|
||||
@@ -14,47 +19,79 @@ comparisons = File {
|
||||
|
||||
declareComparators :: Word -> Gen ()
|
||||
declareComparators bitsize =
|
||||
do let name = "U" ++ show bitsize
|
||||
do let sname = mkIdent ("U" ++ show bitsize)
|
||||
entries = bitsize `div` 64
|
||||
top = entries - 1
|
||||
out "use core::cmp::{Eq,Ordering,PartialEq};"
|
||||
out "#[cfg(test)]"
|
||||
out "use quickcheck::quickcheck;"
|
||||
out ("use super::" ++ name ++ ";")
|
||||
blank
|
||||
implFor "PartialEq" name $
|
||||
wrapIndent "fn eq(&self, other: &Self) -> bool" $
|
||||
do forM_ (reverse [1..top]) $ \ i ->
|
||||
out ("self.value[" ++ show i ++ "] == other.value[" ++ show i ++ "] && ")
|
||||
out "self.value[0] == other.value[0]"
|
||||
blank
|
||||
implFor "Eq" name $ return ()
|
||||
blank
|
||||
implFor "Ord" name $
|
||||
wrapIndent "fn cmp(&self, other: &Self) -> Ordering" $
|
||||
do out ("self.value[" ++ show top ++ "].cmp(&other.value[" ++ show top ++ "])")
|
||||
forM_ (reverse [0..top-1]) $ \ i ->
|
||||
out (" .then(self.value[" ++ show i ++ "].cmp(&other.value[" ++ show i ++ "]))")
|
||||
blank
|
||||
implFor "PartialOrd" name $
|
||||
wrapIndent "fn partial_cmp(&self, other: &Self) -> Option<Ordering>" $
|
||||
out "Some(self.cmp(other))"
|
||||
blank
|
||||
out "#[cfg(test)]"
|
||||
wrapIndent "quickcheck!" $
|
||||
do let transFun n = "fn " ++ n ++ "(a: " ++ name ++ ", b: " ++ name ++
|
||||
", c: " ++ name ++ ") -> bool"
|
||||
wrapIndent (transFun "eq_is_transitive") $
|
||||
out ("if a == c { a == b && b == c } else { a != b || b != c }")
|
||||
blank
|
||||
wrapIndent (transFun "gt_is_transitive") $
|
||||
out ("if a > b && b > c { a > c } else { true }")
|
||||
blank
|
||||
wrapIndent (transFun "ge_is_transitive") $
|
||||
out ("if a >= b && b >= c { a >= c } else { true }")
|
||||
blank
|
||||
wrapIndent (transFun "lt_is_transitive") $
|
||||
out ("if a < b && b < c { a < c } else { true }")
|
||||
blank
|
||||
wrapIndent (transFun "le_is_transitive") $
|
||||
out ("if a <= b && b <= c { a <= c } else { true }")
|
||||
eqStatements = buildEqStatements 0 entries
|
||||
compareExp = buildCompareExp 0 entries
|
||||
out $ show $ pretty' $ [sourceFile|
|
||||
use core::cmp::{Eq,Ordering,PartialEq};
|
||||
#[cfg(test)]
|
||||
use quickcheck::quickcheck;
|
||||
use super::$$sname;
|
||||
|
||||
impl PartialEq for $$sname {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let mut out = true;
|
||||
$@{eqStatements}
|
||||
out
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for $$sname {}
|
||||
|
||||
impl Ord for $$sname {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
$$(compareExp)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for $$sname {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
quickcheck! {
|
||||
fn eq_is_transitive(a: $$sname, b: $$sname, c: $$sname) -> bool {
|
||||
if a == c { a == b && b == c } else { a != b || b != c }
|
||||
}
|
||||
|
||||
fn gt_is_transitive(a: $$sname, b: $$sname, c: $$sname) -> bool {
|
||||
if a > b && b > c { a > c } else { true }
|
||||
}
|
||||
|
||||
fn ge_is_transitive(a: $$sname, b: $$sname, c: $$sname) -> bool {
|
||||
if a >= b && b >= c { a >= c } else { true }
|
||||
}
|
||||
|
||||
fn lt_is_transitive(a: $$sname, b: $$sname, c: $$sname) -> bool {
|
||||
if a < b && b < c { a < c } else { true }
|
||||
}
|
||||
|
||||
fn le_is_transitive(a: $$sname, b: $$sname, c: $$sname) -> bool {
|
||||
if a <= b && b <= c { a <= c } else { true }
|
||||
}
|
||||
}
|
||||
|]
|
||||
|
||||
buildEqStatements :: Word -> Word -> [Stmt Span]
|
||||
buildEqStatements i numEntries
|
||||
| i == (numEntries - 1) =
|
||||
[[stmt| out &= self.value[$$(x)] == other.value[$$(x)]; |]]
|
||||
| otherwise =
|
||||
let rest = buildEqStatements (i + 1) numEntries
|
||||
cur = [stmt| out &= self.value[$$(x)] == other.value[$$(x)]; |]
|
||||
in cur:rest
|
||||
where
|
||||
x = Lit [] (Int Dec (fromIntegral i) Unsuffixed mempty) mempty
|
||||
|
||||
buildCompareExp :: Word -> Word -> Expr Span
|
||||
buildCompareExp i numEntries
|
||||
| i == (numEntries - 1) =
|
||||
[expr| self.value[$$(x)].cmp(&other.value[$$(x)]) |]
|
||||
| otherwise =
|
||||
let rest = buildCompareExp (i + 1) numEntries
|
||||
in [expr| $$(rest).then(self.value[$$(x)].cmp(&other.value[$$(x)])) |]
|
||||
where
|
||||
x = Lit [] (Int Dec (fromIntegral i) Unsuffixed mempty) mempty
|
||||
|
||||
Reference in New Issue
Block a user