Commit 653dcc0c authored by Michael Hanus 's avatar Michael Hanus
Browse files

Model info files are searched also in parent directories

parent 326fe06d
......@@ -36,8 +36,7 @@ The idea and usage of contracts is described in \cite{AntoyHanus12PADL}.
\subsection{Installation}
The current implementation of Curry preprocessor is a package
managed by the Curry Package Manager CPM
(see also Section~\ref{sec-cpm}).
managed by the Curry Package Manager CPM.
Thus, to install the newest version of \code{currypp},
use the following commands:
%
......@@ -467,7 +466,6 @@ Such a data term specification should be stored in Curry program file
as an (exported!) top-level operation type \code{ERD}.
If our example term is defined as a constant in the Curry program
\code{UniERD.curry}, then one has to use the tool \ccode{erd2curry}
(see Sect.~\ref{sec-erd2curry})
to process the ER model so that it can be used
in SQL statements. This tool is invoked with the parameter
\ccode{--cdbi},
......@@ -475,8 +473,7 @@ the (preferably absolute) file name of the SQLite database,
and the name of the Curry program containing the ER specification.
If the SQLite database file does not exist, it will be initialized by the tool.
In our example, we execute the following command
(provided that the tool \code{erd2curry} is already installed,
see Sect.~\ref{sec-erd2curry}):
(provided that the tool \code{erd2curry} is already installed:
%
\begin{curry}
> erd2curry --db `pwd`/Uni.db --cdbi UniERD.curry
......@@ -532,8 +529,30 @@ and generate appropriate Curry library calls.
\subsubsection{SQL Statements as Integrated Code}
After specifying and processing the ER model of the database,
one can write SQL statement in their standard syntax
as integrated code (marked by the prefix \ccode{sql}) in Curry programs.
one can write SQL statements in their standard syntax
as integrated code (marked by the language tag \ccode{sql}) in Curry programs.
Since the SQL translator checks the correct use of these statements
against the ER model, it needs access to the generated info file
\code{Uni\us{}SQLCODE.info}.
This can be ensured in one of the following ways:
\begin{itemize}
\item
The path to the info file is passed as a parameter prefixed by
\ccode{--model:} to the Curry preprocessor, e.g., by the preprocessor
directive
\begin{curry}
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=--model:$\ldots$/Uni_SQLCode.info #-}
\end{curry}
\item
The info file is placed in the same directory as the Curry source file
to be processed or in one of its parent directories.
The directories are searched from the directory of the source file
up to its parent directories.
If one of these directories contain more than one file with the
name \ccode{\ldots{}\us{}SQLCODE.info}, an error is reported.
\end{itemize}
%
After this preparation, one can write SQL statements in the Curry program.
For instance, to retrieve all students from the database, one
can define the following SQL query:
%
......@@ -542,7 +561,7 @@ allStudents :: IO (SQLResult [Student])
allStudents = ``sql Select * From Student;''
\end{curry}
%
Since database accesses might produce errors,
Since the execution of database accesses might produce errors,
the result of SQL statements is always of type
\ccode{SQLResult $\tau$}, where \code{SQLResult} is a type synonym
defined in the \CYS library \code{Database.CDBI.Connection}:
......@@ -563,7 +582,7 @@ immediately, one can also define the above query as follows:
%
\begin{curry}
allStudents :: IO [Student]
allStudents = liftIO fromSQLResult ``sql Select * From Student;''
allStudents = liftM fromSQLResult ``sql Select * From Student;''
\end{curry}
%
In order to get more control on executing the SQL statement,
......@@ -717,14 +736,12 @@ Note that only strict assertion checking is supported
at the moment.
Strict assertion checking might change the operational behavior
of the program.
The notation of contracts has been shortly introduced
in Section~\ref{sec:currycheck:contracts}.
The notation of contracts is defined in \cite{AntoyHanus12PADL}.
To transform such contracts into assertions,
one has to use the option \ccode{contracts} for the preprocessor.
As a concrete example, consider an implementation of quicksort
with a postcondition and a specification as shown in
Section~\ref{sec:currycheck:contracts}
with a postcondition and a specification
(where the code for \code{sorted} and \code{perm} is not shown here):
%
\begin{curry}
......@@ -765,5 +782,5 @@ ERROR: Execution aborted due to contract violation!
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "../../../docs/src/manual"
%%% TeX-master: "main"
%%% End:
......@@ -8,11 +8,11 @@
--- Reads the .info file which contains information about the data model and
--- passes the information to the corresponding subroutines.
--- Aborts compilation process in case a stage returns with an error.
---@author Julia Krone
---@version 0.1
---
--- @author Julia Krone
-- ---------------------------------------------------------------------------
module SQLConverter(parse, readParserInfo, ParserInfo) where
module SQLConverter(parseSQL, readParserInfo, ParserInfo) where
import IO(openFile, IOMode(..), hGetContents)
......@@ -36,8 +36,8 @@ import SQLTyper
--- @param pos - Position of the integrated SQL-String in the orginal file
--- @param code - the SQL-request as string
--- @return A String in Curry-Syntax (CDBI-functions).
parse :: Bool -> Either String ParserInfo -> LangParser
parse withrundb parserInfo pos code =
parseSQL :: Bool -> Either String ParserInfo -> LangParser
parseSQL withrundb parserInfo pos code =
case parserInfo of
Left err -> return (throwPM pos err)
Right pi -> processCompilation withrundb pi pos code
......@@ -48,13 +48,13 @@ parse withrundb parserInfo pos code =
--- @return either an error message or the parser information
readParserInfo :: Int -> String -> IO (Either String ParserInfo)
readParserInfo verb filename = do
when (verb > 0) $ putStrLn $ "Read SQL model info file '" ++filename++ "'..."
when (verb > 0) $ putStrLn $
"Reading SQL model info file '" ++ filename ++ "'..."
handle <- openFile filename ReadMode
contents <- (hGetContents handle)
case (readsQTerm contents) of
[] -> return (Left ("ParserInfo-file was not found"++
" or is corrupted."))
((a,_):_) -> return (Right a)
case readsQTerm contents of
[] -> return (Left "ParserInfo file not found or corrupted.")
((a,_):_) -> return (Right a)
-- auxiliary function to check Result after each stage
checkResult :: PM a -> Either (PM String) (PM a)
......
......@@ -28,11 +28,12 @@
--- @author Jasper Sikorra (with changes by Michael Hanus)
--- @version January 2018
------------------------------------------------------------------------------
module TransICode where
import Directory(getDirectoryContents)
import FilePath ((</>), takeDirectory)
import IO(stderr,hPutStrLn)
import Directory ( getAbsolutePath, getDirectoryContents )
import FilePath ( (</>), joinPath, splitDirectories, takeDirectory )
import IO ( stderr, hPutStrLn )
import List
import System
......@@ -61,10 +62,10 @@ parsers = maybe iden pars
case l of
"sql" -> case model of
Left err -> const (return $ throwPM p err)
_ -> SQLParser.parse True model p
_ -> SQLParser.parseSQL True model p
"sql*" -> case model of
Left err -> const (return $ throwPM p err)
_ -> SQLParser.parse False model p
_ -> SQLParser.parseSQL False model p
"dummy" -> DummyParser.parse p
"format" -> FormatParser.parse "" p
"printf" -> FormatParser.parse "putStr" p
......@@ -127,14 +128,26 @@ tryReadParserInfoFile :: Int -> String -> String
-> IO (Either String ParserInfo)
tryReadParserInfoFile verb model orgfname = do
if null model
then do dirfiles <- getDirectoryContents orgdir
case filter ("_SQLCode.info" `isSuffixOf`) dirfiles of
[] -> return (Left "No .info file provided or found!")
[m] -> readParserInfo verb (orgdir </> m)
_ -> return (Left "Multiple .info files found!")
then do orgdir <- getAbsolutePath (takeDirectory orgfname)
fresult <- findParserInfoFile (splitDirectories orgdir)
case fresult of
Left err -> return (Left err)
Right fname -> readParserInfo verb (orgdir </> fname)
else readParserInfo verb model
where
orgdir = takeDirectory orgfname
findParserInfoFile :: [String] -> IO (Either String String)
findParserInfoFile dirpath = do
let dir = joinPath dirpath
--putStrLn $ "Searching info file in: " ++ dir
dirfiles <- getDirectoryContents dir
case filter ("_SQLCode.info" `isSuffixOf`) dirfiles of
[] -> let uppath = init dirpath
in if null uppath
then return (Left "No .info file provided or found!")
else findParserInfoFile uppath
[m] -> return (Right $ dir </> m)
ms -> return (Left $ "Multiple .info files found in directory '" ++ dir ++
"':\n" ++ unwords ms)
--- Handles the IO and PM monads around the StandardTokens for the
--- concatenation, so they will not disturb in the real concat function
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment