{-# LANGUAGE TypeSynonymInstances, TemplateHaskell, QuasiQuotes, MultiParamTypeClasses, FlexibleInstances, DeriveDataTypeable, ScopedTypeVariables #-}
module Examples.PWS where
import Language.Pads.Padsc
import Language.Forest.Forestc hiding (sources)
import System.IO.Unsafe (unsafePerformIO)
import Language.Pads.GenPretty
import Language.Forest.Graph
[pads|
{- Configuration file for learning demo web site; contains paths to various web site components. -}
data Config_f = Config_f {
header :: [Line StringLn] length 13,
"$host_name =", host_name :: Config_entry_t, -- Name of machine hosting web site
"$static_path =", static_path :: Config_entry_t, -- URL prefix for static content
"$cgi_path =", cgi_path :: Config_entry_t, -- URL prefix for cgi content
"$script_path =", script_path :: Config_entry_t, -- Path to directory of scripts in live web site
"$tmp_root =", tmp_root :: Config_entry_t, -- Path to directory for demo user data
"$pads_home =", pads_home :: Config_entry_t, -- Path to directory containing pads system
"$learn_home =", learn_home :: Config_entry_t, -- Path to directory containing learning system
"$sml_home =", sml_home :: Config_entry_t, -- Path to directory containing SML executable
"$install_src =", install_src :: Config_entry_t, -- Path to directory containing learning demo website source
"$static_dst =", static_dst :: Config_entry_t, -- Path to directory for static content in live web site
"$cgi_dst =", cgi_dst :: Config_entry_t, -- Path to directory for cgi content in live web site site
trailer :: [Line StringLn]
}
type Config_entry_t = Line (" \"", StringC '\"', "\";")
newtype Header_t = Header_t ([Line StringLn] length 13)
{- Fle listing data sources for web site -}
newtype SourceNames_f = SourceNames_f [Line StringLn]
{- Information related to a single user's use of the web site -}
newtype UserEntries_f = UserEntries_f ([Line UserEntry_t] terminator EOR)
{- Each visitor gets assigned a userId that is passed as a ? parameter in URL.
Security considerations preclude using user-modifiable values as part of file paths.
Thus, we map each userId to a corresponding dirId.
The dirId names the directory containing the associated user's data.
A userEntry_t contains a single such mapping.
A file with type userEntries_t describes a collection of such mappings.
-}
data UserEntry_t = UserEntry_t {
"id.", usrId :: Int,
",id.", dirId :: (Int, '.', Int) where <| usrId == fst dirId |>
}
{- Log of requests. Used to prevent denial of service attacks. -}
newtype LogFile_f = LogFile_f [Line LogEntry_t]
{- Request entry. -}
data LogEntry_t = LogEntry_t {
userId :: Int, ',', -- user making request
ip :: IP_t, ',', -- IP address of requestor
script :: StringC ' ', ' ', -- script to be executed
userDir:: StringC ' ', ' ', -- directory to put results, corresponds to user
padsv :: StringC ' ', ' ', -- version of PADS used
sml :: StringSE '[ ]', -- version of SML used
msg :: Maybe StringLn -- optional message
}
type IP_t = (Int, '.', Int, '.', Int, '.', Int)
|]
[forest|
{- Files with various permission settings. -}
type BinaryRO = BinaryFile where <| get_modes this_att == "-rw-r--r--" |>
type BinaryRX = BinaryFile where <| get_modes this_att == "-rwxr-xr-x" |>
type TextRX = TextFile where <| get_modes this_att == "-rwxr-xr-x" |>
type TextRO = TextFile where <| get_modes this_att == "-rw-r--r--" |>
{- Optional binary file with read/execute permission. -}
type OptBinaryRX = Maybe BinaryRX
{- Files with PADS descriptions -}
type Config = File Config_f where <| get_modes this_att == "-rw-r--r--" |>
type SourceNames = File SourceNames_f where <| isReadOnly this_att |>
type UserEntries = File UserEntries_f where <| isReadOnly this_att |>
type LogFile = File LogFile_f where <| isReadOnly this_att |>
{- Directory of image files -}
type Imgs_d = Directory {
logo is "pads_small.jpg" :: BinaryRO,
favicon is "favicon.ico" :: BinaryRO
}
{- Directory of static content -}
type Static_d = Directory {
style_sheet is "pads.css" :: TextRO,
intro_redir is "learning-demo.html" :: TextRO,
title_frame is "atitle.html" :: TextRO,
logo_frame is "top-left.html" :: TextRO,
top_frame is "banner.html" :: TextRO,
empty_frame is "nothing.html" :: TextRO,
images is "images" :: Imgs_d where <| get_modes images_md == "drwxr-xr-x" |>
}
{- Directory of dynamic content -}
type Cgi_d = Directory {
config' is "PLConfig.pm" :: TextRO,
perl_utils is "PLUtilities.pm" :: TextRO,
intro is "learning-demo.cgi" :: TextRX,
intro_nav is "navbar-orig.cgi" :: TextRX,
select_data is "pads.cgi" :: TextRX,
result_nav is "navbar.cgi" :: TextRX,
format_chosen is "data-results.cgi" :: TextRX,
gen_desc is "build-description.cgi" :: TextRX,
get_user_data is "build-roll-your-own.cgi" :: TextRX,
gen_desc_usr is "genData.cgi" :: TextRX,
build_lib is "build-library.cgi" :: TextRX,
build_accum is "build-accum.cgi" :: TextRX,
build_xml is "build-xml.cgi" :: TextRX,
build_fmt is "build-fmt.cgi" :: TextRX
}
{- Directory of shell scripts invoked by CGI to run learning system -}
type Scripts_d = Directory {
rlearn :: TextRX, -- Shell script for running PADS comiler on stock format
rlearnown is "rlearn-own" :: TextRX, -- Shell script for running PADS compiler on user format
raccum is "r-accum" :: TextRX, -- Shell script to generate and run accumulator
rxml is "r-xml" :: TextRX, -- Shell script to generate and run XML converter
rfmt is "r-fmt" :: TextRX, -- Shell script to generate and run formating program
rlibrary :: TextRX -- Shell script to build PADS library
}
{- Directory containing administrative files used by demo web site -}
type Info_d = Directory {
sources is "sampleFiles" :: SourceNames, -- List of source data files whose formats can be learned
users is "userFile" :: UserEntries, -- Mapping from userIDs to associated directory names
logFile is "logFile" :: LogFile -- Log of server actions.
}
{- Collection of files named by sources containing actual data. -}
type DataSource_d(sources :: [String]) = [ s :: TextFile | s <- sources ]
{- Type of a symbolic link with pointing to source-}
type SymLink_f (path :: FilePath) = SymLink where <| this == path |>
{- Directory of optional links to source data files -}
type Data_d ((root,sources) :: (FilePath, [String])) = Directory {
datareps is [s :: Maybe TextFile | s <- sources],
datalinks is [s :: Maybe (SymLink_f <| root++"/"++ s |>) | s <- sources]
}
{- Directory that stores the generated machine-dependent output for data source named source -}
type MachineDep_d (source :: String) = Directory {
pads_c is <| source ++ ".c" |> :: TextRO, -- Generated C source for PADS description
pads_h is <| source ++ ".h" |> :: TextRO, -- Generated C header for PADS description
pads_o is <| source ++ ".o" |> :: BinaryRO, -- Compiled library for PADS description
pads_pxml is <| source ++ ".pxml" |> :: TextRO, -- PADS description in xml syntax
pads_xsd is <| source ++ ".xsd" |> :: TextRO, -- Xschema of XML syntax for source description
pads_acc is <| source ++ "-accum"|> :: OptBinaryRX, -- Optional generated accumulator program
pads_fmt is <| source ++ "-fmt" |> :: OptBinaryRX, -- Optional generated formatting program
pads_xml is <| source ++ "-xml" |> :: OptBinaryRX -- Optional generated XML conversion program
}
{- Directory that stores the generated output for data source named "source". -}
type Example_d (source :: String) = Directory {
pads_p is <| source ++ ".p" |> :: TextRO, -- PADS/C description of data source
pads_pml is <| source ++ ".pml" |> :: Maybe TextRO, -- PADS/ML description of data source
vanilla is "vanilla.p" :: TextRO, -- input tokenization
makefile is "GNUmakefile" :: TextFile, -- Makefile
machine is <| envVar "AST_ARCH"|> :: Maybe (MachineDep_d source), -- Platform dependent files
accum_c is <| source ++ "-accum.c" |> :: Maybe TextRO, -- Template for accumulator program
accum_out is <| source ++ "-accum.out"|> :: Maybe TextRO, -- ASCII Accumulator output
accum_xml_out is <| source ++ "-accum_xml.out"|> :: Maybe TextRO, -- XML Accumulator output
xml_c is <| source ++ "-xml.c"|> :: Maybe TextRO, -- Template for XML converter
xml_out is <| source ++ "-xml.out"|> :: Maybe TextRO, -- XML representation of source
xml_xsd is <| source ++ ".xsd" |> :: Maybe TextRO, -- Xschema for XML representation of source
fmt_c is <| source ++ "-fmt.c" |> :: Maybe TextRO, -- Template for formatting program
fmt_out is <| source ++ "-fmt.out" |> :: Maybe TextRO -- Formatted representation of source
}
{- Directory that stores all information for one user. -}
type User_d(arg@ (r, sources) :: (FilePath, [String])) = Directory {
dataSets is "data" :: Maybe (Data_d arg),
runExamples is [ s :: Maybe (Example_d s) | s <- sources]
}
{- Collection of directories containing temporary information for all users. -}
type Users_d((r,info) :: (FilePath, Info_d)) =
[userDir :: User_d <|(r, getSources info) |> | userDir <- <| userNames info |> ]
{- Top-level of PADS website. -}
type Website_d(config::FilePath) = Directory {
c is config :: Config, -- Configuration file with locations of other components
static_content is <| gstatic_dst c |> :: Static_d, -- Static web site content
dynamic_content is <| gcgi_dst c |> :: Cgi_d, -- Dynamic web site content
scripts is <| gscript_path c |> :: Scripts_d, -- Shell scripts invoked by cgi to run learning system
admin_info is <| gstatic_dst c |> :: Info_d, -- Administrative information about website
data_dir is <| (glearn_home c)++"/examples/data" |>
:: DataSource_d <|(getSources admin_info)|>, -- Stock data files for website
usr_data is <| gtmp_root c |> :: Users_d <|(get_fullpath data_dir_md, admin_info)|> -- User-specific information
}
|]
{- HASKELL HELPER FUNCTIONS -}
isReadOnly md = get_modes md == "-rw-r--r--"
{- Function userName gets the list of user directorn names from an info structure. -}
userNames info = getUserEntries (users info)
getUserEntries (UserEntries (UserEntries_f users)) = map userEntryToFileName users
userEntryToFileName userEntry = pairToFileName (dirId userEntry)
pairToFileName (n1, n2) = "id."++(show n1)++"."++(show n2)
{- Helper functiosn to convert a Config entry to a FileName -}
ghost_name (Config c) = host_name c
gstatic_path (Config c) = static_path c
gcgi_path (Config c) = cgi_path c
gscript_path (Config c) = script_path c
glearn_home (Config c) = learn_home c
gtmp_root (Config c) = tmp_root c
gstatic_dst (Config c) = static_dst c
gcgi_dst (Config c) = cgi_dst c
{- Loading functions -}
config_location = "/Users/kfisher/Sites/cgi-bin/PLConfig.PM"
doLoadWebsite = website_d_load config_location "/Users/kfisher/Sites"
{- print graph of website -}
doGraph md = mdToPDF md "Examples/website.pdf"
users_dir = "/Users/kfisher/Sites/cgi-bin/gen"
(users'_rep, users'_md) :: (Users_d, Users_d_md) = unsafePerformIO $ load1 ("/Users/kfisher/pads/infer/examples/data", info_rep) users_dir
user_dir = "/Users/kfisher/Sites/cgi-bin/gen/id.1192115633.7"
(userE_rep, userE_md) :: (User_d, User_d_md) = unsafePerformIO $ load1 ("/Users/kfisher/pads/infer/examples/data", ["ai.3000"]) user_dir
graphUserIO = mdToPDF userE_md "Examples/users.pdf"
example_dir = "/Users/kfisher/Sites/cgi-bin/gen/id.1192115633.7/ai.3000"
(example_rep, example_md) :: (Example_d, Example_d_md) = unsafePerformIO $ load1 "ai.3000" example_dir
machine_dir = "/Users/kfisher/Sites/cgi-bin/gen/id.1192115633.7/ai.3000/darwin.i386"
(machinedep_rep, machinedep_md) :: (MachineDep_d, MachineDep_d_md) = unsafePerformIO $ load1 "ai.3000" machine_dir
root_data_dir = "/Users/kfisher/pads/infer/examples/data"
data_dir_path = "/Users/kfisher/Sites/cgi-bin/gen/id.1192115633.7/data"
(data_d_rep, data_d_md) :: (Data_d, Data_d_md) = unsafePerformIO $ load1 (root_data_dir, datasources) data_dir_path
link_path = "Examples/data/Simple/mylink"
(link_rep,link_md) :: (SymLink_f, SymLink_f_md) = unsafePerformIO $ load1 "quantum" link_path
info_dir = "/Users/kfisher/Sites"
(info_rep, info_md) :: (Info_d, Info_d_md) = unsafePerformIO $ load info_dir
dataSource_dir = "/Users/kfisher/pads/infer/examples/data"
(datasource_rep, datasource_md) :: (DataSource_d, DataSource_d_md) = unsafePerformIO $ load1 datasources dataSource_dir
--getStrings (Pstringln (PstringSE s)) = s
getStrings s = s
getSources' (SourceNames (SourceNames_f pstrlns)) = map getStrings pstrlns
getSources :: Info_d -> [String]
getSources info = getSources' (sources info)
datasources :: [String]
datasources = getSources info_rep
scripts_dir = "/Users/kfisher/Sites/cgi-bin"
(scripts_rep, scripts'_md) :: (Scripts_d, Scripts_d_md) = unsafePerformIO $ load scripts_dir
cgi_dir = "/Users/kfisher/Sites/cgi-bin"
(cgi_rep, cgi_md) :: (Cgi_d, Cgi_d_md) = unsafePerformIO $ load cgi_dir
static_dir = "/Users/kfisher/Sites"
(static_rep, static_md) :: (Static_d, Static_d_md) = unsafePerformIO $ load static_dir
image_dir = "/Users/kfisher/Sites/images"
(img_rep, img_md) :: (Imgs_d, Imgs_d_md) = unsafePerformIO $ load image_dir
config_file = "/Users/kfisher/Sites/cgi-bin/PLConfig.pm"
(config_rep, config_md) :: (Config_f, Config_f_md) = unsafePerformIO $ parseFile config_file
(head_rep, head_md) :: (Header_t, Header_t_md) = unsafePerformIO $ parseFile config_file
sampleFiles = "/Users/kfisher/Sites/sampleFiles"
(sample_rep, sample_md) :: (SourceNames_f, SourceNames_f_md) = unsafePerformIO $ parseFile sampleFiles
userEntries = "/Users/kfisher/Sites/userFile"
(user_rep, user_md) :: (UserEntries_f, UserEntries_f_md) = unsafePerformIO $ parseFile userEntries
logFiles = "/Users/kfisher/Sites/logFile"
(logFiles_rep, logFiles_md) :: (LogFile_f, LogFile_f_md) = unsafePerformIO $ parseFile logFiles