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 = "<form>Gimme <input type=text name=henry></form>\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 print (if henry ="" then blankForm else implode(rev(explode henry)) end val q = (filter (fn ("QUERY_STRING",_)=>true| _ => false)) o (map ((twain implode) o (split_on "=") o explode)); fun action nil = pream ^ blankForm | action((_,"")::_) = pream ^ blankForm | action((_,h)::_) = pream ^ "Your string backwards is: "^ implode(rev(#2 (split_on "=" (explode h)))) ^ "\n"; exportFn("/usr/local/etc/httpd/cgi-bin/andrew6", print o action o q o #2);