From bbabbd0161ab6e633f7d7027e0167892633519f7 Mon Sep 17 00:00:00 2001 From: Matt McCutchen Date: Sat, 27 Aug 2011 12:02:35 -0400 Subject: [PATCH] Add command-line interface ./match (adapted from POPL 2012 version). --- program/.gitignore | 1 + program/ArrayStuff.hs | 3 +++ program/Main.hs | 40 ++++++++++++++++++++++++++++++++++++++++ program/Makefile | 10 +++++++--- program/example.in | 4 ++++ 5 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 program/Main.hs create mode 100644 program/example.in diff --git a/program/.gitignore b/program/.gitignore index b3652c0..7c789e1 100644 --- a/program/.gitignore +++ b/program/.gitignore @@ -1,3 +1,4 @@ /*.hi /*.o /graph-*.ps +/match diff --git a/program/ArrayStuff.hs b/program/ArrayStuff.hs index ceb7516..df0a969 100644 --- a/program/ArrayStuff.hs +++ b/program/ArrayStuff.hs @@ -15,6 +15,9 @@ array2DtoListOfLists arr = let ((xlo, ylo), (xhi, yhi)) = bounds arr in map (\x -> map (\y -> arr ! (x, y)) $ range (ylo, yhi)) $ range (xlo, xhi) +listOfListsToArray2D ll = + listArray ((0, 0), (length ll - 1, length (head ll) - 1)) $ concat ll + -- Use instead of amap when the array implementation needs to change. -- E.g., mapping an unboxed array to an array whose elements must be boxed. amap2 f arr = funcArray (bounds arr) (\i -> f (arr ! i)) diff --git a/program/Main.hs b/program/Main.hs new file mode 100644 index 0000000..4487508 --- /dev/null +++ b/program/Main.hs @@ -0,0 +1,40 @@ +import PMInstance +import PMDefaults +import ProposalMatcher +import System.IO +import Data.Array.IArray +import Data.Array.Unboxed +import ArrayStuff +import Text.CSV + +-- Command-line interface with simple tab-separated input/output formats. +-- ./match if c == '\t' then ',' else if c == ',' then '\t' else c) s +removeQuotes s = filter (\c -> not (c == '"')) s + +-- Some versions of Text.CSV do not use or accept a trailing newline; compensate for that. +removeTrailingNewline s = if not (null s) && last s == '\n' then init s else s +addTrailingNewline s = if not (null s) && last s /= '\n' then s ++ ['\n'] else s + +parseTSV fname str = case parseCSV fname (swapTabCommaIn $ removeTrailingNewline str) of + Left pe -> Left pe + Right ll -> Right $ map (map swapTabCommaIn) ll +printTSV ll = addTrailingNewline $ removeQuotes $ swapTabCommaIn $ printCSV $ map (map swapTabCommaIn) ll + +main = do + incsv <- hGetContents stdin + -- handle errors another day, or let the platform do it + let Right inll = parseTSV "standard input" incsv + let loadList = head inll + let numRvrs = length loadList + let loadA = listArray (0, numRvrs-1) (map read loadList) + let numProps = length (tail inll) + -- explicit type on the next line appears to be necessary + let pxarr = listOfListsToArray2D (tail inll) :: Array (Int,Int) String + -- careful, we end up transposing the array in here + let prefA = funcArray ((0,0), (numRvrs-1,numProps-1)) (\(i,j) -> read (pxarr ! (j, i))) + let theInst = PMInstance numRvrs numProps loadA prefA + let PMatching theMatching = doMatching pmDefaults theInst + hPutStr stdout $ printTSV $ map (\(i, j) -> map show [i, j]) theMatching diff --git a/program/Makefile b/program/Makefile index 78eb667..d72db83 100644 --- a/program/Makefile +++ b/program/Makefile @@ -2,8 +2,12 @@ # -cpp: Handle GHC 6.6.1 compatibility checks. # -fglasgow-exts: Handle rank-2 type of RandomizedMonad, among other things. all: - ghc -cpp -fglasgow-exts --make -c *.hs +# ghc -cpp -fglasgow-exts --make -c *.hs + ghc -cpp -fglasgow-exts --make *.hs -o match all-optimized: - ghc -cpp -fglasgow-exts --make -O -hisuf O.hi -osuf O.o -c *.hs +# ghc -cpp -fglasgow-exts --make -O -hisuf O.hi -osuf O.o -c *.hs + ghc -cpp -fglasgow-exts --make -O -hisuf O.hi -osuf O.o *.hs -o match.O clean: - rm -f *.hi *.o + rm -f *.hi *.o match + +# Necessary libraries (on Fedora): ghc-fgl, ghc-csv. Others I miss? diff --git a/program/example.in b/program/example.in new file mode 100644 index 0000000..167622a --- /dev/null +++ b/program/example.in @@ -0,0 +1,4 @@ +1 1 1 1 1 +15 10 15 40 20 +30 7 10 15 15 +15 25 20 20 15 -- 2.34.1