-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Execute as a script #276
base: main
Are you sure you want to change the base?
Execute as a script #276
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.
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.
We need a fairly detailed description of what this does and how it works, and any new interfaces/signatures, and whether the top-level pervasive environment is changed. When an SML program is invoked as a "script", is it loaded and run in the REPL? Is the SML program that is run as a script an SML source file or is it a stand-alone program with an associated heap-image created by exportFn? In other words, is the goal to make the sml command behave like a Unix shell? |
HI Dave, The pull request is still in draft, I will be adding all the details before I submit the request. |
Ok, that’s what I expected, but I thought I’d give a potentially useful “prompt” about what we would like to see as documentation of the changes.
Also keep in mind that if and when it is merged into legacy, we are likely to also want to merge into the smlnj/smlnj (“development”, but really the continuing release) repository.
Also, I have been looking into the state of the compiler+CM “architecture”, which as become rather muddled. So I am interested in whether your work will impinge on architectural issues. We need to clarify the relation between CM and the interactive REPL, and investigate the idea of a “batch compilation” where stand-alone programs are built without using the REPL, its top-level environment, and exportFn.
Dave
On Apr 15, 2023, at 10:50 AM, dn2007hw ***@***.***> wrote:
HI Dave, The pull request is still in draft, I will be adding all the details before I submit the request.
—
Reply to this email directly, view it on GitHub <#276 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AAGXNPKOAH4KOM6R2YM4TO3XBLNW3ANCNFSM6AAAAAAW7RHZI4>.
You are receiving this because you commented.
David MacQueen
***@***.***
|
Thanks for that summary. This makes it fairly clear what you are doing. I’m not sure how your “silenceCompiler” function works.
Dave
On Apr 15, 2023, at 10:58 AM, dn2007hw ***@***.***> wrote:
Execute-as-a-script.txt <https://github.com/smlnj/legacy/files/11240286/Execute-as-a-script.txt>
—
Reply to this email directly, view it on GitHub <#276 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AAGXNPILMHHTDWE2QRRIE73XBLOUPANCNFSM6AAAAAAW7RHZI4>.
You are receiving this because you commented.
David MacQueen
***@***.***
|
silenceCompiler function is not part of this patch, I have removed the reference. It's part of next patch, I will be adding the details in that. |
We should think about the name of the command-line option. We currently do not use names like Also, the code can be tightened up a bit and should be made more robust. For example, it might be more direct to process the first line of the script using (* if the first line of the input stream begins with "#!", then consume the line
* and return `true`; otherwise return `false` and do not advance the input.
*)
fun checkSharpbang inS = let
val inS' = TextIO.getInstream inS
in
case TextIO.StreamIO.inputLine inS'
of SOME(firstLn, inS'') =>
if String.isPrefix "#!" firstLn
then (TextIO.setInstream(inS, inS''); true)
else false
| _ => false
(* end case *)
end |
This seems like a great feature to add, but I wanted to add my 2 cents about how to handle the shebang. I think it's also important to not require a command-line flag. Tools such as #! /usr/bin/env cargo
//! ```cargo
//! [dependencies]
//! serde = "1.0.215"
//! ```
use serde::ser::{Serialize};
fn main () {
println!("Hello from Rust!");
} This could be integrated into SML/NJ by parsing the first comment in the file, and extracting arguments if the comment is of a certain form. #! /usr/bin/env sml
(*#script -Cmlrisc.disable-jump-chain-elim $smlnj-lib.cm $pp-lib.cm *)
(* Executing this file runs `sml -Cmlrisc.disable-jump-chain-elim '$smlnj-lib.cm' '$pp-lib.cm' <file.sml>`
val () = print "Hello from SML/NJ!\n" Handling the shebang in the lexer also makes it possible to write SML files that act as both libraries and scripts. #! /usr/bin/env sml
structure MyModule : sig
val foo : unit -> unit
end = struct
fun internal () = "Internal"
fun foo () = print (internal ())
fun test () =
if internal () = "Internal" then () else raise Fail "Test failure"
val () = if !SMLofNJ.isScript then test () else ()
end Running the file would execute the script, but it could also be loaded like a normal file that defines a structure. |
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. 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
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.
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.
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
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
$ ./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
val y = "Hello World y\n" : string
Hello World y
val z = "Hello World z\n" : string
Hello World z
$
Test Script #2 (sample script with forced error)
#!/usr/bin/env -Ssml --script
;(--SML--)
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
$ ./sample
Standard ML of New Jersey (32-bit) v110.99.3 [built: Sat Apr 15 18:38:28 2023]
val x = "Hello World x\n" : string
Hello World x
val y = "Hello World y\n" : string
./exml07:7.18-8.4 Error: syntax error: deleting SEMICOLON VAL
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