Artifact 636370f08c051cf2b13d8cae1cbfc2e8adfb9937
1 /**
2 * Authors: k.inaba
3 * License: NYSL 0.9982 (http://www.kmonos.net/nysl/)
4 *
5 * Entry point for Polemy interpreter.
6 */
7 module main;
8 import std.stdio;
9 import std.algorithm;
10 import std.array;
11 import polemy.value;
12 import polemy.failure;
13 import polemy.parse;
14 import polemy.ast;
15 import polemy.eval;
16 import polemy.layer;
17
18 enum VersionNoMajor = 0;
19 enum VersionNoMinor = 1;
20 enum VersionNoRev = 0;
21
22 /// Read-Eval-Print-Loop
23
24 class REPL
25 {
26 /// Load the prelude environment
27 this()
28 {
29 ctx = createGlobalContext();
30 }
31
32 /// Print the version number etc.
33 void greet()
34 {
35 writefln("Welcome to Polemy %d.%d.%d", VersionNoMajor, VersionNoMinor, VersionNoRev);
36 }
37
38 /// Run one file on the global scope
39 void runFile(string filename)
40 {
41 eval(parseFile(filename), ctx, false, ValueLayer);
42 }
43
44 /// Repeat the singleInteraction
45 void replLoop()
46 {
47 while( singleInteraction() ) {}
48 }
49
50 /// Read one line from stdin, and do some reaction
51 bool singleInteraction()
52 {
53 writef(">> ", lineno);
54 string line = readln();
55 if( line.startsWith("exit") || line.startsWith("quit") )
56 return false;
57 try {
58 if( tryRun(line) )
59 writeln(lastVal);
60 } catch(Throwable e) {
61 writeln(e);
62 }
63 return true;
64 }
65
66 private:
67 Table ctx;
68 string buf;
69 Value lastVal;
70 int lineno = 1;
71 int nextlineno = 1;
72
73 bool tryRun( string s )
74 {
75 scope(failure)
76 { buf = ""; lineno = nextlineno; }
77
78 buf ~= s;
79 nextlineno ++;
80 try
81 { lastVal = eval(parseString(buf, "<REPL>", lineno), ctx, false, ValueLayer); }
82 catch( UnexpectedEOF )
83 { return false; } // wait
84 buf = "";
85 lineno = nextlineno;
86 return true;
87 }
88 }
89
90 /// Advance args[] to point the argument list fed to the script.
91 /// Returns the name of the source file to run, or returns "" if
92 /// no filename was given. Also, returns to libs[] the list of
93 /// library source to load.
94
95 string parseArgv(ref string[] args, out string[] libs)
96 {
97 args.popFront();
98
99 while( !args.empty && args.front=="-l" ) {
100 args.popFront();
101 if( !args.empty ) {
102 libs ~= args.front();
103 args.popFront();
104 }
105 }
106
107 if( args.empty )
108 return "";
109 else {
110 scope(exit) args.popFront;
111 return args.front;
112 }
113 }
114
115 /// Entry point.
116
117 void main( string[] args )
118 {
119 string[] libs;
120 string src = parseArgv(args, libs);
121
122 auto r = new REPL;
123 if( src.empty )
124 r.greet();
125 foreach(lb; libs)
126 r.runFile(lb);
127 if( src.empty )
128 r.replLoop();
129 else
130 r.runFile(src);
131 }