|
View:
New views
1 Messages
—
Rating Filter:
Alert me
|
|
|
issues writing SML/NJ scriptsDear SML/NJ gurus,
Naturally, I'd like to use SML/NJ for writing scripts. I've managed to get something working somewhat okay (appended below), but I have discovered that I can't silence certain messages from the compiler. (I'm using version 110.54 that comes from the Ubuntu Dapper Drake repositories.) Here are the main issues I'd like to get some help with: 1. How do I completely silence the “[autoloading]” messages and the “[opening FILE.sml]” messages? Supposedly CM.Control.verbose controls this, but it has no effect on this at all for me. It doesn't matter whether I do “#set CM.Control.verbose false” from the REPL or “-Ccm.verbose=false” from the command line. Right now I am modifying Control.Print.out, and this works, but I can't figure out how to do this early enough to silence every message. And of course there is no way to modify Control.Print.out from the command line. And also this silences everything, unless I do a fancy implementation of the say function that decides which strings to print. 2. How do I silence the “Standard ML of New Jersey” banner message? The above issues are the important ones for me, because they make SML/NJ scripts useless in situations where what gets sent to stdout matters. Any help will be appreciated. Here are some other issues: 3. How do I find out which command-line arguments have been handled by CM so that I can handle the others? There seems to be no way to do this short of duplicating all the logic that CM uses. 4. How do I get CM to ignore arguments after a certain point in the argument list, so they will not cause warnings or errors? Yes, I know I can just avoid having my file return control to the command-line processor, but I'd like to be able to allow doing this when debugging so that execution will continue into the REPL. There seems to be no way to accomplish what I want. Here are some things that would make my life easier, but are less important than the things above: 5. It would be helpful if I could pass SML code on the command line instead of via stdin or by files named on the command line. 6. It would be useful if SML/NJ could do something nice with UNIX #! lines. Something like Perl's -x command-line option which tells Perl to skip everything until a line beginning with a particular fixed string. This would allow starting SML/NJ scripts with #!/usr/bin/sml or #!/bin/sh without needing to do lots of tedious work to avoid SML/NJ parsing the stuff at the front of the file. Right now I have to copy the SML code into a temporary file (using bash's “here document” mechanism) instead of just using the script file. 7. It would be nice if I could tell SML/NJ how to treat a file mentioned on the command line even though the file's name doesn't end in one of the extensions “.sml”, “.sig”, “.fun”, or “.cm”. Right now I have to make a symbolic link to /dev/fd/X that ends in “.sml”. And I have to make a temporary directory to have a secure place to put the symbolic link. And then I have to make sure the temporary directory gets cleaned up, so I can't just exec SML/NJ but need to leave a bash process hanging around. (I suppose I could do the cleanup in SML, but I have to set up cleanup code in bash anyway in case invoking SML/NJ fails.) 8. It would be nice if there was a way to add definitions to the environment seen by a nested invocation of “use” _before_ the current invocation ends. Right now I have to break the input to SML/NJ into 2 files, and then invocations of “use” from the 2nd file can use declarations made by the 1st file. This is awkward. 9. It would be nice to be able to silence messages listing new declarations added to the top-level environment without also silencing everything else from the compiler. I will appreciate hearing any comments on how to accomplish what I am trying to do. -- Thanks, Joe ---------------------------------------------------------------------- #!/bin/bash #********************************************************************** # SML/NJ script template by Joe Wells ********************************* #********************************************************************** # Tested with SML/NJ version 110.54 on Ubuntu Dapper Drake. *********** #********************************************************************** #** SML/NJ script startup boilerplate, ignore ************************* #********************************************************************** TmpDir="`mktemp -d -t smlnj-script.XXXXXX`" CleanUp () { rm -r "$TmpDir"; } trap 'CleanUp; exit 1' INT TERM HUP trap CleanUp EXIT ln -s /dev/fd/4 "$TmpDir/a.sml" ln -s /dev/fd/5 "$TmpDir/b.sml" sml -Ccm.verbose=false "$TmpDir/a.sml" "$TmpDir/b.sml" XyzzyPlugh "$0" "$@" 3<&0 <<'AAAA' 4<&0- <<'BBBB' 5<&0- 0<&3- (**********************************************************************) (** boilerplate definitions, available to evalled code ****************) (**********************************************************************) local val original_Control_Print_out = ! Control.Print.out; in fun unsilence_compiler () = Control.Print.out := original_Control_Print_out; fun silence_compiler () = Control.Print.out := { flush = fn () => (), say = fn _ => () }; (* Don't show declarations added to the top-level environment or further autoloading messages. Disable next line if you want type error messages. *) val _ = silence_compiler (); end (* Arrgh! The code in system/smlnj/internal/int-sys.sml seems to unconditionally print the "Standard ML of New Jersey" banner and has already done so. This is done with print rather than Control.Print.say, so even if we had already run silence_compiler it would still be printed. Also, messages about the loading of this file and the autoloading of something (which is not identified) have already been printed. These use Control.Print.say, but have already been printed. Of course, this wouldn't be necessary at all if the command-line option -Ccm.verbose=false worked as advertised. It seems to have no effect. It certainly has no effect on autoloading messages. *) (* Here is an example of providing definitions that can be used by configuration files which will be evalled. *) datatype option_data = STR of string | INT of int; val options_state : (string * option_data) list ref = ref nil; fun set_option name value = options_state := (name, value)::(! options_state); AAAA (**********************************************************************) (** more boilerplate definitions, but not available to evalled code ***) (**********************************************************************) fun get_option name = case (List.find (fn (n,_) => n = name) (! options_state)) of NONE => NONE | SOME (_,value) => SOME value; (* Maybe I should pass the command-line arguments another way, because there is no good way to automatically determine which are handled by CM, plus any options for the script will still be handled by CM after this code is done, so it interferes with trying to continue on into the REPL (read-eval-print loop) when debugging. *) fun find_real_args ("XyzzyPlugh"::rest) = rest | find_real_args (_::rest) = find_real_args rest | find_real_args nil = raise (Fail "magic word sentinel argument missing") val argv = find_real_args (CommandLine.arguments ()); (**********************************************************************) (** start of your SML/NJ script ***************************************) (**********************************************************************) (* Here is an example of loading a config file and relying on the compiler to parse and type-check it. As you can see, we can ignore syntax and type errors in the config file if we want to. *) (use "smlnj-script-config") handle _ => (); case (get_option "input-data") of NONE => raise (Fail "no input data") | SOME (STR stuff) => print ("input data string: ["^stuff^"]\n") | SOME (INT stuff) => print ("input data int: ["^(Int.toString stuff)^"]\n"); List.app (fn x => print ("command-line argument: ["^x^ "]\n")) argv; (**********************************************************************) (** end of your SML/NJ script *****************************************) (**********************************************************************) (**********************************************************************) (** more boilerplate code follows *************************************) (**********************************************************************) (* For debugging, you might want to comment out the next line, and then SML/NJ will enter the top-level REPL when your code is done. *) ignore (OS.Process.exit OS.Process.success); (* WARNING: If we continue on to the REPL, then the remaining command-line arguments will be processed by the code in cm/main/cm-boot.sml! Hopefully they will not be recognized and will just cause harmless error messages. There appears to be nothing we can do to stop this without also preventing the REPL from being entered. *) (* We need to (re)enable the compiler to speak to us when we enter the REPL. *) unsilence_compiler (); BBBB -- Heriot-Watt University is a Scottish charity registered under charity number SC000278. ------------------------------------------------------------------------------ Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are powering Web 2.0 with engaging, cross-platform capabilities. Quickly and easily build your RIAs with Flex Builder, the Eclipse(TM)based development software that enables intelligent coding and step-through debugging. Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com _______________________________________________ Smlnj-list mailing list Smlnj-list@... https://lists.sourceforge.net/lists/listinfo/smlnj-list |
| Free embeddable forum powered by Nabble | Forum Help |