GIML: How to create an executable
The exportFn command
exportFn : string * (string list * string list -> unit) -> unit
This function takes the file name of required executable and a function
which describes its behaviour. It unceremoniously dumps the user out
of ML and leaves a massive executable on your disk.
The "action" function takes two lists as input - the first is a list
of parameters - starting with the executable name (c.f. the argv parameter
in C). The second parameter is a list of system variable in the format:
"name=value"
The action function has unit as output - this means that you
must use print to make the program do something visible.
Smaller executables
The simplest is "Hello world" weighs in at
an astounding 3 megabytes on my system.
Try running sml.noshare or sml-noshare if you have it.
Example "Hello World"
The following creates a file called hello which you
can execute from the unix prompt.
exportFn("hello", fn _ => print "Hello World\n");
Demonstrator
Execute the following to see the behaviour of the executable:
fun println s = print(s^"\n");
fun action(paramList, envVarList) = app println(
["Your parameters:"] @ paramList @ ["","Your variables"] @ envVarList);
exportFn("demo", action);
CGI example
The second parameter to export is a list of environment variable/
value pairs. CGI uses the environment variable QUERY_STRING to
communicate HTML form variables.
val pream = "Content-type: text/html\n\n";
val blankForm = "\n"
fun twain f (x,y) = (f x,f y);
fun split_on x l = let
fun s a (h::t) = if x=h then (rev a,t) else s (h::a) t
| s a nil = (rev a,nil)
in twain implode (s nil (explode l)) end;
fun chop_on x s = let val (f,r)=split_on x s in
f::(if r="" then nil else chop_on x r) end
fun lookup d k' ((k,v)::t) = if k=k' then v else lookup d k' t
| lookup d _ nil = d;
fun action(vars) = let
val query_string = lookup "" "QUERY_STRING" (map (split_on "=") vars)
val henry = lookup "" "henry" (map (split_on "=")
(chop_on "&" query_string))
in pream^(if henry ="" then blankForm else implode(rev(explode henry)))end;
exportFn("/usr/local/etc/httpd/cgi-bin/andrew1",
fn (_,vars) => print(action vars) );