root/tags/lastPhobos/mdcl.d

Revision 173, 6.3 kB (checked in by JarrettBillingsley, 1 year ago)

--

Line 
1 /******************************************************************************
2 License:
3 Copyright (c) 2007 Jarrett Billingsley
4
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the
7 use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it freely,
11 subject to the following restrictions:
12
13     1. The origin of this software must not be misrepresented; you must not
14     claim that you wrote the original software. If you use this software in a
15     product, an acknowledgment in the product documentation would be
16     appreciated but is not required.
17
18     2. Altered source versions must be plainly marked as such, and must not
19     be misrepresented as being the original software.
20
21     3. This notice may not be removed or altered from any source distribution.
22 ******************************************************************************/
23
24 module mdcl;
25
26 import minid.compiler;
27 import minid.minid;
28 import minid.types;
29
30 import std.cstream;
31 import std.path;
32 import std.stdio;
33 import std.stream;
34
35 void printVersion()
36 {
37     writefln("MiniD Command-Line interpreter beta");
38 }
39
40 void printUsage()
41 {
42     printVersion();
43     writefln("Usage:");
44     writefln("\tmdcl [flags] [filename [args]]");
45     writefln();
46     writefln("Flags:");
47     writefln("\t-i      Enter interactive mode, after executing any script file.");
48     writefln("\t-v      Print the version of the CLI.");
49     writefln("\t-h      Print this message and end.");
50     writefln("\t-I path Specifies an import path to search when importing modules.");
51     writefln();
52     writefln("If mdcl is called without any arguments, it will be as if you passed it");
53     writefln("the -v and -i arguments (it will print the version and enter interactive");
54     writefln("mode).");
55     writefln();
56     writefln("If the filename has no extension, it will be treated as a MiniD import-");
57     writefln("style module name.  So \"a.b\" will look for a module named b in the a");
58     writefln("directory.  The -I flag also affects the search paths used for this.");
59     writefln();
60     writefln("When passing a filename followed by args, all the args will be available");
61     writefln("to the script by using the vararg expression.  The arguments will all be");
62     writefln("strings.");
63     writefln();
64     writefln("In interactive mode, you will be given a >>> prompt.  When you hit enter,");
65     writefln("you may be given a ... prompt.  That means you need to type more to make");
66     writefln("the code complete.  Once you enter enough code to make it complete, the");
67     writefln("code will be run.  If there is an error, the code buffer is cleared.");
68     writefln("To end interactive mode, either use the function \"exit();\", or type");
69    
70     version(Windows)
71     {
72         writefln("the end-of-file character (Ctrl-Z) and hit enter to end, or force exit");
73         writefln("by hitting Ctrl-C.");
74     }
75     else
76         writefln("the end-of-file character (Ctrl-D) and hit enter to end.");
77 }
78
79 const char[] Prompt1 = ">>> ";
80 const char[] Prompt2 = "... ";
81
82 void main(char[][] args)
83 {
84     bool printedVersion = false;
85     bool interactive = false;
86     char[] inputFile;
87     char[][] scriptArgs;
88     char[][] importPaths;
89
90     if(args.length == 1)
91     {
92         printVersion();
93         interactive = true;
94     }
95
96     _argLoop: for(int i = 1; i < args.length; i++)
97     {
98         switch(args[i])
99         {
100             case "-i":
101                 interactive = true;
102                 break;
103
104             case "-v":
105                 if(printedVersion == false)
106                 {
107                     printedVersion = true;
108                     printVersion();
109                 }
110                 break;
111                
112             case "-h":
113                 printUsage();
114                 return;
115                
116             case "-I":
117                 i++;
118                
119                 if(i >= args.length)
120                 {
121                     writefln("-I must be followed by a path");
122                     printUsage();
123                     return;
124                 }
125                
126                 importPaths ~= args[i];
127                 break;
128
129             default:
130                 if(args[i][0] == '-')
131                 {
132                     writefln("Invalid flag '%s'", args[i]);
133                     printUsage();
134                     return;
135                 }
136
137                 inputFile = args[i];
138                 scriptArgs = args[i + 1 .. $];
139                 break _argLoop;
140         }
141     }
142
143     MDState state = MDInitialize();
144    
145     foreach(path; importPaths)
146         MDGlobalState().addImportPath(path);
147
148     if(inputFile.length > 0)
149     {
150         MDModuleDef def;
151
152         if(inputFile.length >= 3 && inputFile[$ - 3 .. $] == ".md")
153             def = compileModule(inputFile);
154         else if(inputFile.length >= 4 && inputFile[$ - 4 .. $] == ".mdm")
155             def = MDModuleDef.loadFromFile(inputFile);
156
157         MDValue[] params = new MDValue[scriptArgs.length];
158
159         foreach(i, arg; scriptArgs)
160             params[i] = arg;
161
162         if(def is null)
163         {
164             try
165             {
166                 if(MDGlobalState().loadModuleFromFile(state, utf.toUTF32(inputFile), params) is null)
167                     writefln("Error: could not find module '%s'", inputFile);
168             }
169             catch(MDException e)
170             {
171                 writefln("Error: ", e);
172                 writefln(MDState.getTracebackString());
173             }
174         }
175         else
176         {
177             try
178                 MDGlobalState().initializeModule(state, def, params);
179             catch(MDException e)
180             {
181                 writefln("Error: ", e);
182                 writefln(MDState.getTracebackString());
183             }
184         }
185     }
186
187     if(interactive)
188     {
189         char[] buffer;
190         bool run = true;
191
192         MDGlobalState().globals["exit"d] = MDGlobalState().newClosure
193         (
194             (MDState s, uint numParams)
195             {
196                 run = false;
197                 return 0;
198             }, "exit"
199         );
200
201         version(Windows)
202             writefln("Type EOF (Ctrl-Z) and hit enter to end, or use the \"exit();\" function.");
203         else
204             writefln("Type EOF (Ctrl-D) and hit enter to end, or use the \"exit();\" function.");
205            
206         writef(Prompt1);
207
208         while(run)
209         {
210             char[] line = din.readLine();
211
212             if(din.eof())
213                 break;
214
215             buffer ~= line;
216
217             scope MemoryStream s = new MemoryStream(buffer);
218
219             bool atEOF = false;
220             MDFuncDef def;
221
222             try
223                 def = compileStatements(s, "stdin", atEOF);
224             catch(MDCompileException e)
225             {
226                 if(atEOF)
227                 {
228                     writef(Prompt2);
229                 }
230                 else
231                 {
232                     writefln(e);
233                     writefln();
234                     writef(Prompt1);
235                     buffer.length = 0;
236                 }
237
238                 continue;
239             }
240
241             try
242             {
243                 scope closure = MDGlobalState().newClosure(def);
244                 state.easyCall(closure, 0, MDValue(MDGlobalState().globals.ns));
245             }
246             catch(MDException e)
247             {
248                 writefln("Error: ", e);
249                 writefln(MDState.getTracebackString());
250                 writefln();
251             }
252
253             writef(Prompt1);
254             buffer.length = 0;
255         }
256     }
257 }
Note: See TracBrowser for help on using the browser.