cpsa-4.4.1: src/CPSA/SAS/Main.hs
-- Summarize CPSA output as a formula in coherent logic
-- Copyright (c) 2011 The MITRE Corporation
--
-- This program is free software: you can redistribute it and/or
-- modify it under the terms of the BSD License as published by the
-- University of California.
module Main (main) where
import System.IO
import CPSA.Lib.SExpr
import CPSA.Signature (Sig, defaultSig, loadSig)
import CPSA.Algebra
import CPSA.Lib.Entry
import CPSA.Options
import CPSA.SAS.SAS
-- Algebra names
algs :: [String]
algs = [name, alias]
main :: IO ()
main =
do
let options = algOptions name
let interp = algInterp name algs
(p, (output, alg, margin)) <- start options interp
h <- outputHandle output
herald p margin h alg
-- Handle the herald
herald :: PosHandle -> Int -> Handle -> String -> IO ()
herald p margin h alg =
do
x <- readSExpr p
case x of
Nothing -> abort "Empty input"
Just x@(L pos (S _ "herald" : _ : xs)) ->
do
writeSExpr h margin x
hPutStrLn h ""
sig <- loadSig pos (assoc "lang" xs)
let nom = getAlgName xs alg
select p margin h sig nom Nothing
Just (L _ (S _ "comment" : _)) ->
herald p margin h alg
x ->
select p margin h defaultSig alg x
select :: PosHandle -> Int -> Handle -> Sig ->
String -> Maybe (SExpr Pos) -> IO ()
select p margin h sig alg x =
do
writeComment h margin cpsaVersion
writeComment h margin "Coherent logic"
let stepper = step h alg origin margin
let state = (sig, [], [])
case () of
_ | alg == name || alg == alias ->
case x of
Nothing -> go stepper p state
_ ->
do
next <- stepper state x
go stepper p next
| otherwise ->
abort ("Bad algebra: " ++ alg)
hClose h
go :: (a -> Maybe (SExpr Pos) -> IO a) -> PosHandle -> a -> IO ()
go f p a =
loop a
where
loop a =
do
x <- readSExpr p
case x of
Nothing ->
do
_ <- f a x
return ()
Just _ ->
do
a <- f a x
loop a
step :: Handle -> String -> Gen -> Int -> State ->
Maybe (SExpr Pos) -> IO State
step output _ _ margin state@(_, [], [])
(Just sexpr@(L _ (S _ "comment" : _))) =
do
writeLnSExpr output margin sexpr
return state
step output name origin margin state sexpr =
do
x <- tryIO (sas name origin state sexpr)
case x of
Left err ->
abort err
Right (acc, Nothing) ->
after output margin acc sexpr
Right (acc, Just x) ->
do
writeLnSExpr output margin x
after output margin acc sexpr
after :: Handle -> Int -> State -> Maybe (SExpr Pos) -> IO State
after output margin state (Just sexpr@(L _ (S _ "defprotocol" : _))) =
do
writeLnSExpr output margin sexpr
return state
after _ _ state _ =
return state
getAlgName :: [SExpr a] -> String -> String
getAlgName xs name =
case assoc "algebra" xs of
[] -> name
[S _ nom] -> nom
_ -> error "Bad algbra field an herald"
-- Lookup value in alist, appending values with the same key
assoc :: String -> [SExpr a] -> [SExpr a]
assoc key alist =
concat [ rest | L _ (S _ head : rest) <- alist, key == head ]