blob: 037a75895acb08db2e70b6fd55e593ed547827ae [file] [log] [blame]
swissChili923bd532021-12-08 22:48:58 -08001#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!
11namespace ReadLine
12{
13#include <readline/readline.h>
14#include <readline/history.h>
15}
16
17
18Repl::Repl()
19{
20}
21
22char *Repl::prompt()
23{
24 static char p[] = "\033[36mREFAL >\033[0m ";
25 return p;
26}
27
28QString Repl::readLine()
29{
30 char *line = ReadLine::readline(prompt());
31
32 if (!line)
33 {
34 _running = false;
35 return "";
36 }
37
swissChili923bd532021-12-08 22:48:58 -080038 QString string = QString::fromUtf8(line);
39
40 free(line);
41
42 return string;
43}
44
swissChilibd2a90d2021-12-09 10:36:14 -080045void Repl::addHistory(QString line)
46{
47 ReadLine::add_history(line.toUtf8());
48}
49
swissChili923bd532021-12-08 22:48:58 -080050void Repl::start()
51{
52 while (_running)
53 {
swissChilibd2a90d2021-12-09 10:36:14 -080054 QString line = readLine().trimmed();
swissChili923bd532021-12-08 22:48:58 -080055
56 QList<AstNode> expr;
57
swissChilic046cdf2021-12-09 19:59:51 -080058 if (!line.isEmpty())
59 addHistory(line);
60
61 ParseResult ret;
swissChilibd2a90d2021-12-09 10:36:14 -080062
swissChili923bd532021-12-08 22:48:58 -080063 if (trySpecialCase(line))
64 {}
swissChilic046cdf2021-12-09 19:59:51 -080065 else if ((ret = tryEvaluate(line, &expr)))
swissChili923bd532021-12-08 22:48:58 -080066 {
67 bool okay = true;
68 QList<Token> out;
69
swissChili2506b922022-02-15 21:07:20 -080070 for (const AstNode &node : qAsConst(expr))
swissChili923bd532021-12-08 22:48:58 -080071 {
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 {
swissChilibd2a90d2021-12-09 10:36:14 -080089 qDebug().noquote() << pprint(out);
swissChili923bd532021-12-08 22:48:58 -080090 }
91 }
swissChilic046cdf2021-12-09 19:59:51 -080092 else if (ret.status() == ParseResult::INCOMPLETE)
93 {
swissChili2506b922022-02-15 21:07:20 -080094 qDebug() << "Parse error: incomplete input:" << ret.message();
95 ReadLine::rl_insert_text("Hello there!");
96 ReadLine::rl_redisplay();
swissChilic046cdf2021-12-09 19:59:51 -080097 }
swissChili923bd532021-12-08 22:48:58 -080098 else
99 {
swissChili2506b922022-02-15 21:07:20 -0800100 qDebug() << "Parse error:" << ret.message();
swissChili923bd532021-12-08 22:48:58 -0800101 }
102 }
103}
104
swissChilic046cdf2021-12-09 19:59:51 -0800105ParseResult Repl::trySpecialCase(QString line)
swissChili923bd532021-12-08 22:48:58 -0800106{
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
swissChilic046cdf2021-12-09 19:59:51 -0800124ParseResult Repl::tryEvaluate(QString line, QList<AstNode> *expr)
swissChili923bd532021-12-08 22:48:58 -0800125{
126 Parser parser(line);
127 Function func;
128
swissChilic046cdf2021-12-09 19:59:51 -0800129 ParseResult ret;
130
swissChili2506b922022-02-15 21:07:20 -0800131 if ((ret = parser.parseFunctionDefinition(&func)))
swissChili923bd532021-12-08 22:48:58 -0800132 {
133 _eval.addFunction(func);
134 *expr = {};
135
136 return true;
137 }
swissChilic046cdf2021-12-09 19:59:51 -0800138 else if (ret.status() == ParseResult::INCOMPLETE)
139 {
140 return ret;
141 }
142 else
143 {
144 return parser.parseMany(expr);
145 }
swissChili923bd532021-12-08 22:48:58 -0800146}