Created
March 20, 2015 05:20
-
-
Save gbluma/79e802872dab3e1f3363 to your computer and use it in GitHub Desktop.
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
// TODO: support more than just linux/osx | |
include "std/posix/filesystem"; | |
// TODO: add this to std/io/textio.flx, it's missing | |
gen fopen_append : string -> ofile = '::std::fopen($1.c_str(), "a")'; | |
object Repl () = { | |
// if a line starts with these, it is considered a definition and is retained. | |
val defs_regex = RE2("\s*(val|var|fun|gen|proc|struct).*"); | |
val temp_dir = "/tmp/"; | |
// generate a random session id | |
val session = str(rand()); | |
// build some paths | |
val f_repl_path = temp_dir + session + "_repl.flx"; // immediate commands to execute | |
val f_defs_path = temp_dir + session + "_defs.flx"; // keep track of saved definitions | |
val f_repl_path_prev = temp_dir + session + "_repl_prev.flx"; // backup of commands for rollback | |
val f_defs_path_prev = temp_dir + session + "_defs_prev.flx"; // backup of definitions for rollback | |
// mutable state | |
var previous_line = ""; | |
var inputLine = ""; | |
// ------------------------------------------------------------------ | |
// Show the >>> at the start of the line | |
method proc printLinePrefix = { | |
print ">>> "; | |
fflush stdout; // flush to *actually* show text | |
} | |
// ------------------------------------------------------------------ | |
method proc init() { | |
// delete old garbage definitions first | |
var result = PosixFileSystem::unlink_file(f_defs_path); | |
// prompt user for input | |
println "Garrett's Fake Felix REPL (version 0.0.1)"; | |
printLinePrefix(); | |
} | |
// ------------------------------------------------------------------ | |
method proc work() { | |
// prime input for loop | |
inputLine = rstrip(stdin.readln); // rstrip to remove newline (interferes with regex) | |
// loop on input | |
while (inputLine.len > 0.size) do | |
match Match(defs_regex, inputLine) with | |
| None => | |
// ... just a command, run it | |
// write new line to repl (always overwrite) | |
var repl_filehandle = fopen_output(f_repl_path); | |
if FileStat::fileexists(f_defs_path) do | |
write(repl_filehandle, "include '"+temp_dir+session+"_defs"+"';\n"); | |
done | |
write(repl_filehandle, inputLine); | |
fflush repl_filehandle; | |
repl_filehandle.fclose(); | |
// evaluate repl | |
val executed = System::system("flx " + f_repl_path + " 2>/dev/null"); | |
(executed > 0) ?? println("Couldn't interpret file " + f_repl_path); | |
| Some ?b => | |
// ... a definition, save it. | |
// write new line to defs | |
val defs_filehandle = fopen_append(f_defs_path); | |
write(defs_filehandle, inputLine + "\n"); | |
fflush defs_filehandle; | |
defs_filehandle.fclose(); | |
// evaluate defs and recover if failed | |
val x = System::system("flx " + f_defs_path + " 2>/dev/null"); | |
(x > 0) ?? var y = System::system("cat " + f_defs_path_prev + " > " + f_defs_path ); | |
(x == 0) ?? var z = System::system("cat " + f_defs_path + " > " + f_defs_path_prev ); | |
endmatch; | |
printLinePrefix(); | |
// capture more input from stdin | |
inputLine = rstrip(readln(stdin)); | |
done | |
} | |
// ------------------------------------------------------------------ | |
method proc cleanup() { | |
// clean up output file | |
var defs_deleted = PosixFileSystem::unlink_file(f_defs_path); | |
(defs_deleted > 0) ?? println("Couldn't delete file " + f_defs_path ); | |
} | |
} | |
val r = Repl(); | |
r.init(); | |
r.work; | |
r.cleanup; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment