1 /** 2 * This module contains the main function for the REPL. It also runs script files. 3 */ 4 module app; 5 6 import std.file: readText, FileException; 7 import std.getopt; 8 import std.stdio; 9 import std..string: strip; 10 11 import arsd.terminal; 12 13 import mildew.compiler : Compiler; 14 import mildew.exceptions; 15 import mildew.interpreter; 16 import mildew.lexer; 17 import mildew.parser; 18 import mildew.types; 19 20 /** 21 * This runs a script program and prints the appropriate error message when a script exception is caught. 22 */ 23 void evaluateWithErrorChecking(Interpreter interpreter, in string source, in string fileName, bool printDisasm) 24 { 25 try 26 { 27 ScriptAny result; 28 if(source == "" && fileName != "<stdin>") 29 result = interpreter.evaluateFile(fileName, printDisasm); 30 else 31 result = interpreter.evaluate(source, printDisasm); 32 writeln("The program successfully returned " ~ result.toString); 33 } 34 catch(ScriptCompileException ex) 35 { 36 stderr.writeln("In file " ~ fileName); 37 stderr.writefln("%s", ex); 38 } 39 catch(ScriptRuntimeException ex) 40 { 41 stderr.writeln("In file " ~ fileName); 42 stderr.writefln("%s", ex); 43 if(ex.thrownValue.type != ScriptAny.Type.UNDEFINED) 44 stderr.writefln("Value thrown: %s", ex.thrownValue); 45 } 46 catch(Compiler.UnimplementedException ex) 47 { 48 stderr.writeln(ex.msg); 49 } 50 } 51 52 private void printUsage() 53 { 54 stderr.writeln("Usage: dmildew_run <scriptfile> [options]"); 55 stderr.writeln(" dmildew_run [options]"); 56 stderr.writeln("Options: -usevm : Use bytecode generation instead of tree walker (experimental)"); 57 stderr.writeln(" -h : Print this usage message"); 58 } 59 60 /** 61 * Main function for the REPL or interpreter. If no command line arguments are specified, it enters 62 * interactive REPL mode, otherwise it attempts to execute the first argument as a script file. 63 */ 64 int main(string[] args) 65 { 66 auto terminal = Terminal(ConsoleOutputType.linear); 67 bool useVM = false; 68 bool printVMDebugInfo = false; 69 bool printDisasm = false; 70 71 try 72 { 73 auto options = cast(immutable)getopt(args, 74 "usevm|u", &useVM, 75 "verbose|v", &printVMDebugInfo, 76 "disasm|d", &printDisasm); 77 if(options.helpWanted) 78 { 79 printUsage(); 80 return 1; 81 } 82 } 83 catch(Exception ex) 84 { 85 printUsage(); 86 return 64; 87 } 88 89 auto interpreter = new Interpreter(useVM, printVMDebugInfo); 90 interpreter.initializeStdlib(); 91 92 if(args.length > 1) 93 { 94 string[] fileNames = args[1..$]; 95 foreach(fileName ; fileNames) 96 evaluateWithErrorChecking(interpreter, "", fileName, printDisasm); 97 } 98 else 99 { 100 while(true) 101 { 102 try 103 { 104 string input = strip(terminal.getline("mildew> ")); 105 if(input == "#exit" || input == "") 106 break; 107 while(input.length > 0 && input[$-1]=='\\') 108 { 109 input = input[0..$-1]; 110 input ~= "\n" ~ strip(terminal.getline(">>> ")); 111 } 112 writeln(); 113 evaluateWithErrorChecking(interpreter, input, "<stdin>", printDisasm); 114 } 115 catch(UserInterruptionException ex) 116 { 117 break; 118 } 119 } 120 writeln(""); 121 } 122 return 0; 123 }