Open
Conversation
Changes made in cm-boot.sml to recognise the new command line parameter passed from script. a) In function args, line added to recognise the new command-line parameter ‘--script’, and a new function ‘nextargscript’ is called to initiate the process of the file. b) In function init(), the new function (useScriptFile) is added as one of the parameter passed. c) In function procCmdLine (), new function processFileScript is added to process the script file, function will check for whether the file passed on is a script file starting with ‘#!’ thru another new function checkSharpbang, consumes the first line thru another new function eatuntilneline and pass the remaining content of the file to function useScriptFile.
In functor BootEnvF, cminit function declaration is amended to include the newly added function useScriptFile.
A new function (useScriptFile) is added to Backend.Interact structure, which takes the file name and its content as a stream and process the stream by passing it to EvalLoop.evalStream. The compiler messages are muted and unmuted before the processing of the file. a) New function declaration is added to interact.sig, b) New function definition is added to interact.sml,
New signature MUTECOMPILER is defined with all the global variables and functions that are part of Structure Mutecompiler, New structure Mutecompiler has two core functions silencecompiler and unsilencecompier. a. silencecompiler function mutes the compiler messages by saving the current printing limits in a ref cell and then set them all to zero. b. unsilencecompiler function unmutes the compiler messages by restoring the printing limits. c. dummyfn function which does nothing is created and invoked to preload the Mutecompiler structure before the script is passed to evalloop, this is to supress the structure auto-loading logs in the script results.
A new structure Mutecompiler is declared within signature BACKEND. New structure Mutecompiler is defined within functor BackendFn.
INDEX, MAP and core.cm are updated with definitions for signature MUTECOMPILER and structure Mutecompiler.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Script execution made simple with SML/NJ
Submitted By: Dayanandan Natarajan
Supervisor: Joe Wells
School of Mathematical and Computer Sciences
Heriot-Watt University
Objective
Primary objective of this change is to give the programmers and developers the capability of running a SML program as a script. Also the capability to mute and unmute compiler messages. Programmers and developers can write a SML program and run the program like a script over the command prompt.
Files modified
smlnj/base/cm/main/cm-boot.sml
smlnj/base/system/smlnj/internal/boot-env-fn.sml
smlnj/base/compiler/TopLevel/interact/interact.sig
smlnj/base/compiler/TopLevel/interact/interact.sml
smlnj/base/compiler/TopLevel/backend/backend-fn.sml
smlnj/base/compiler/TopLevel/backend/backend.sig
smlnj/base/compiler/TopLevel/interact/mutecompiler.sig (New component)
smlnj/base/compiler/TopLevel/interact/mutecompiler.sml (New component)
smlnj/base/compiler/INDEX
smlnj/base/compiler/MAP
smlnj/base/compiler/core.cm
Change details
A new function (useScriptFile) is added to Backend.Interact structure, which takes the file name and its content as a stream and process the stream by passing it to EvalLoop.evalStream. The compiler messages are muted and unmuted before the processing of the file. (Functions silenceCompiler, dummyfn and unsilenceCompiler will be explained later in this document)
a) New function declaration is added to interact.sig,
b) New function definition is added to interact.sml,
The following changes were made in cm-boot.sml to recognise the new command line parameter passed from script.
a) In function args, line added to recognise the new command-line parameter ‘--script’, and a new function ‘nextargscript’ is called to initiate the process of the file.
b) In function init(), the new function (useScriptFile) is added as one of the parameter passed,
fun init (bootdir, de, er, useStream, useScriptFile, useFile, errorwrap, icm) = let
c) In function procCmdLine (), new function processFileScript is added to process the script file, function will check for whether the file passed on is a script file starting with ‘#!’ thru another new function checkSharpbang, consumes the first line thru another new function eatuntilneline and pass the remaining content of the file to function useScriptFile.
In functor BootEnvF, cminit function declaration is amended to include the newly added function useScriptFile.
functor BootEnvF (datatype envrequest = AUTOLOAD | BARE
val architecture: string
val cminit : string * DynamicEnv.env * envrequest
* (TextIO.instream -> unit)(* useStream )
* (string * TextIO.instream -> unit) ( useScriptFile )
* (string -> unit) ( useFile )
* ((string -> unit) -> (string -> unit))
( errorwrap *)
* ({ manageImport:
Ast.dec * EnvRef.envref -> unit,
managePrint:
Symbol.symbol * EnvRef.envref -> unit,
getPending : unit -> Symbol.symbol list }
-> unit)
-> (unit -> unit) option
val cmbmake: string * bool -> unit) :> BOOTENV = struct
A new structure Mutecompiler is declared within signature BACKEND,
signature BACKEND = sig
structure Profile : PROFILE
structure Compile : COMPILE
structure Interact : INTERACT
structure Mutecompiler : MUTECOMPILER
structure Machine : MACHINE
val architecture: string
val abi_variant: string option
end
New structure Mutecompiler is defined within functor BackendFn,
structure Mutecompiler = Mutecompiler
mutecompiler.sig
New signature MUTECOMPILER is defined with all the global variables and functions that are part of Structure Mutecompiler,
mutecompiler.sml
New structure Mutecompiler has the following core functions,
a. silencecompiler function mutes the compiler messages by saving the current printing limits in a ref cell, then set them all to zero and stashes the compiler messages by saving the value of Control.Print.out in a ref cell.
b. unsilencecompiler function unmutes the compiler messages by restoring the printing limits and value of Control.Print.out from stored ref cell.
c. printStashedCompilerOutput function prints the stashed compiler messages to the user.
d. dummyfn function which does nothing is created and invoked to preload the Mutecompiler structure before the script is passed to evalloop, this is to supress the structure auto-loading logs in the script results.
INDEX, MAP and core.cm are updated with definitions for signature MUTECOMPILER and structure Mutecompiler.
a. INDEX
MUTECOMPILER
TopLevel/interact/mutecompiler.sig
Mutecompiler
TopLevel/interact/mutecompiler.sml
b. MAP
interact/
envref.sml
supports top-level environment management
defs: ENVREF, EnvRef : ENVREF
evalloop.sig,sml
top-level read-eval-print loop
defs: EVALLOOP, EvalLoopF: TOP_COMPILE => EVALLOOP
interact.sig,sml
creating top-level loops
defs: INTERACT, Interact: EVALLOOP => INTERACT
mutecompiler.sig,sml
allow compiler silencing
defs: MUTECOMPILER, Mutecompiler
c. core.cm
TopLevel/interact/mutecompiler.sig
TopLevel/interact/mutecompiler.sml
Writing a script
The script should start with ‘#!’ in the first line followed by the environment location, command-line parameters ‘-Ssml’ and ‘—script’, a new line and then followed by the SML code or program.
Example script named ‘sample’,
--------------beginning of the script-------------
#!/usr/bin/env -Ssml –script
;(--SML--)
val () = print "Hello World\n";
--------------end of the script---------------------
Running a script
Additional functions
a. The compiler messages can be muted/suppressed by invoking the silencecompiler function as below in the script,
val _ = Backend.Mutecompiler.silenceCompiler ();
b. The compiler messages can be unmuted by invoking the unsilencecompiler function as below in the script,
val _ = Backend.Mutecompiler.unsilenceCompiler ();
c. Whenever an error is encountered in compiling, by default only last 5 lines of the suppressed compiler messages are printed to the user and this limit can be pre-set in script as below,
Backend.Mutecompiler.printlineLimit := 10;
d. Whenever compiler messages are muted by calling silenceCompiler function, variable declarations are stashed with ‘#’ in suppressed compiler messages to save memory. To see the original content in case of debugging, this can be retrieved by amending the Control print parameters and restoring the print limits by increasing the string depth and calling the restorePrintingLimits function as below in the script,
Control.Print.stringDepth := 999;
val _ = Backend.Mutecompiler.restorePrintingLimits ();
SML/NJ Version used
Our development and testing is based on Standard ML of New Jersey (32-bit) v110.99.3 on an Intel based macOS 10.13.16.
Test Details
Test Script #1
#!/usr/bin/env -Ssml --script
;(* SML code starts here *)
val x = "Hello World x\n";
val () = print x;
val y = "Hello World y\n";
val () = print y;
val z = "Hello World z\n";
val () = print z;
Test Result #1
$ ./exml07
Standard ML of New Jersey (32-bit) v110.99.3 [built: Mon Apr 10 18:03:19 2023]
val x = "Hello World x\n" : string
Hello World x
val y = "Hello World y\n" : string
Hello World y
val z = "Hello World z\n" : string
Hello World z
$
Test Script #2
#!/usr/bin/env -Ssml --script
;(* SML code starts here *)
val _ = Backend.Mutecompiler.silenceCompiler ();
val x = "Hello World x\n";
val () = print x;
val y = "Hello World y\n";
val () = print y;
val z = "Hello World z\n";
val () = print z;
Test Result #2
$ ./exml07
Standard ML of New Jersey (32-bit) v110.99.3 [built: Mon Apr 10 18:03:19 2023]
Hello World x
Hello World y
Hello World z
$
Test Script #3
#!/usr/bin/env -Ssml --script
;(--SML--)
val x = "Hello World x\n";
val () = print x;
val _ = Backend.Mutecompiler.silenceCompiler ();
val y = "Hello World y\n";
val () = print y;
val _ = Backend.Mutecompiler.unsilenceCompiler ();
val z = "Hello World z\n";
val () = print z;
Test Result #3
$ ./sample
Standard ML of New Jersey (32-bit) v110.99.3 [built: Mon Apr 10 18:03:19 2023]
val x = "Hello World x\n" : string
Hello World x
Hello World y
val z = "Hello World z\n" : string
Hello World z
$
Test Script #4
#!/usr/bin/env -Ssml --script
;(--SML--)
val x = "Hello World x\n";
val () = print x;
val _ = Backend.Mutecompiler.silenceCompiler ();
Control.Print.stringDepth := 999;
val _ = Backend.Mutecompiler.restorePrintingLimits ();
val y = "Hello World y\n";
val () == print y;
val _ = Backend.Mutecompiler.unsilenceCompiler ();
val z = "Hello World z\n";
val () = print z;
Test Result #4
$ ./sample
Standard ML of New Jersey (32-bit) v110.99.3 [built: Mon Apr 10 18:03:19 2023]
val x = "Hello World x\n" : string
Hello World x
The last 5 lines 31 through 35 of suppressed compiler messages are:
[library $SMLNJ-MLRISC/IA32.cm is stable]
[autoloading done]
val it = # : unit
val y = "Hello World y\n" : string
./exml07:8.18-9.4 Error: syntax error: deleting SEMICOLON VAL
End of suppressed compiler messages._____
uncaught exception Compile [Compile: "syntax error"]
raised at: ../compiler/Parse/main/smlfile.sml:19.24-19.46
../compiler/TopLevel/interact/evalloop.sml:45.54
../compiler/TopLevel/interact/evalloop.sml:306.20-306.23$