Start working on switching to language-rust as a generator, for fun.

This commit is contained in:
2019-10-22 20:12:08 -07:00
parent d7665acf64
commit 2400b10fbc
9 changed files with 723 additions and 404 deletions

View File

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