swissChili | 923bd53 | 2021-12-08 22:48:58 -0800 | [diff] [blame] | 1 | #include <stdio.h> |
2 | #include <string.h> | ||||
3 | |||||
4 | #include <QDebug> | ||||
5 | |||||
6 | #include "Repl.h" | ||||
7 | #include "Parser.h" | ||||
8 | #include "PPrint.h" | ||||
9 | |||||
10 | // JANK! librl isn't namespaced! | ||||
11 | namespace ReadLine | ||||
12 | { | ||||
13 | #include <readline/readline.h> | ||||
14 | #include <readline/history.h> | ||||
15 | } | ||||
16 | |||||
17 | |||||
18 | Repl::Repl() | ||||
19 | { | ||||
20 | } | ||||
21 | |||||
22 | char *Repl::prompt() | ||||
23 | { | ||||
24 | static char p[] = "\033[36mREFAL >\033[0m "; | ||||
25 | return p; | ||||
26 | } | ||||
27 | |||||
28 | QString Repl::readLine() | ||||
29 | { | ||||
30 | char *line = ReadLine::readline(prompt()); | ||||
31 | |||||
32 | if (!line) | ||||
33 | { | ||||
34 | _running = false; | ||||
35 | return ""; | ||||
36 | } | ||||
37 | |||||
swissChili | 923bd53 | 2021-12-08 22:48:58 -0800 | [diff] [blame] | 38 | QString string = QString::fromUtf8(line); |
39 | |||||
40 | free(line); | ||||
41 | |||||
42 | return string; | ||||
43 | } | ||||
44 | |||||
swissChili | bd2a90d | 2021-12-09 10:36:14 -0800 | [diff] [blame] | 45 | void Repl::addHistory(QString line) |
46 | { | ||||
47 | ReadLine::add_history(line.toUtf8()); | ||||
48 | } | ||||
49 | |||||
swissChili | 923bd53 | 2021-12-08 22:48:58 -0800 | [diff] [blame] | 50 | void Repl::start() |
51 | { | ||||
52 | while (_running) | ||||
53 | { | ||||
swissChili | bd2a90d | 2021-12-09 10:36:14 -0800 | [diff] [blame] | 54 | QString line = readLine().trimmed(); |
swissChili | 923bd53 | 2021-12-08 22:48:58 -0800 | [diff] [blame] | 55 | |
56 | QList<AstNode> expr; | ||||
57 | |||||
swissChili | c046cdf | 2021-12-09 19:59:51 -0800 | [diff] [blame] | 58 | if (!line.isEmpty()) |
59 | addHistory(line); | ||||
60 | |||||
61 | ParseResult ret; | ||||
swissChili | bd2a90d | 2021-12-09 10:36:14 -0800 | [diff] [blame] | 62 | |
swissChili | 923bd53 | 2021-12-08 22:48:58 -0800 | [diff] [blame] | 63 | if (trySpecialCase(line)) |
64 | {} | ||||
swissChili | c046cdf | 2021-12-09 19:59:51 -0800 | [diff] [blame] | 65 | else if ((ret = tryEvaluate(line, &expr))) |
swissChili | 923bd53 | 2021-12-08 22:48:58 -0800 | [diff] [blame] | 66 | { |
67 | bool okay = true; | ||||
68 | QList<Token> out; | ||||
69 | |||||
swissChili | 2506b92 | 2022-02-15 21:07:20 -0800 | [diff] [blame^] | 70 | for (const AstNode &node : qAsConst(expr)) |
swissChili | 923bd53 | 2021-12-08 22:48:58 -0800 | [diff] [blame] | 71 | { |
72 | RuntimeResult res = _eval.evaluate(node, VarContext()); | ||||
73 | |||||
74 | if (res.success()) | ||||
75 | { | ||||
76 | out.append(res.result()); | ||||
77 | } | ||||
78 | else | ||||
79 | { | ||||
80 | qDebug() << "Failed to evaluate" << node; | ||||
81 | qDebug() << res.message(); | ||||
82 | okay = false; | ||||
83 | break; | ||||
84 | } | ||||
85 | } | ||||
86 | |||||
87 | if (okay) | ||||
88 | { | ||||
swissChili | bd2a90d | 2021-12-09 10:36:14 -0800 | [diff] [blame] | 89 | qDebug().noquote() << pprint(out); |
swissChili | 923bd53 | 2021-12-08 22:48:58 -0800 | [diff] [blame] | 90 | } |
91 | } | ||||
swissChili | c046cdf | 2021-12-09 19:59:51 -0800 | [diff] [blame] | 92 | else if (ret.status() == ParseResult::INCOMPLETE) |
93 | { | ||||
swissChili | 2506b92 | 2022-02-15 21:07:20 -0800 | [diff] [blame^] | 94 | qDebug() << "Parse error: incomplete input:" << ret.message(); |
95 | ReadLine::rl_insert_text("Hello there!"); | ||||
96 | ReadLine::rl_redisplay(); | ||||
swissChili | c046cdf | 2021-12-09 19:59:51 -0800 | [diff] [blame] | 97 | } |
swissChili | 923bd53 | 2021-12-08 22:48:58 -0800 | [diff] [blame] | 98 | else |
99 | { | ||||
swissChili | 2506b92 | 2022-02-15 21:07:20 -0800 | [diff] [blame^] | 100 | qDebug() << "Parse error:" << ret.message(); |
swissChili | 923bd53 | 2021-12-08 22:48:58 -0800 | [diff] [blame] | 101 | } |
102 | } | ||||
103 | } | ||||
104 | |||||
swissChili | c046cdf | 2021-12-09 19:59:51 -0800 | [diff] [blame] | 105 | ParseResult Repl::trySpecialCase(QString line) |
swissChili | 923bd53 | 2021-12-08 22:48:58 -0800 | [diff] [blame] | 106 | { |
107 | if (line.startsWith(".")) | ||||
108 | { | ||||
109 | if (line == ".q" || line == ".quit") | ||||
110 | { | ||||
111 | _running = false; | ||||
112 | } | ||||
113 | else | ||||
114 | { | ||||
115 | qDebug().noquote() << "Unknown special command, try .help"; | ||||
116 | } | ||||
117 | |||||
118 | return true; | ||||
119 | } | ||||
120 | |||||
121 | return false; | ||||
122 | } | ||||
123 | |||||
swissChili | c046cdf | 2021-12-09 19:59:51 -0800 | [diff] [blame] | 124 | ParseResult Repl::tryEvaluate(QString line, QList<AstNode> *expr) |
swissChili | 923bd53 | 2021-12-08 22:48:58 -0800 | [diff] [blame] | 125 | { |
126 | Parser parser(line); | ||||
127 | Function func; | ||||
128 | |||||
swissChili | c046cdf | 2021-12-09 19:59:51 -0800 | [diff] [blame] | 129 | ParseResult ret; |
130 | |||||
swissChili | 2506b92 | 2022-02-15 21:07:20 -0800 | [diff] [blame^] | 131 | if ((ret = parser.parseFunctionDefinition(&func))) |
swissChili | 923bd53 | 2021-12-08 22:48:58 -0800 | [diff] [blame] | 132 | { |
133 | _eval.addFunction(func); | ||||
134 | *expr = {}; | ||||
135 | |||||
136 | return true; | ||||
137 | } | ||||
swissChili | c046cdf | 2021-12-09 19:59:51 -0800 | [diff] [blame] | 138 | else if (ret.status() == ParseResult::INCOMPLETE) |
139 | { | ||||
140 | return ret; | ||||
141 | } | ||||
142 | else | ||||
143 | { | ||||
144 | return parser.parseMany(expr); | ||||
145 | } | ||||
swissChili | 923bd53 | 2021-12-08 22:48:58 -0800 | [diff] [blame] | 146 | } |