blob: b52b84322b1dc7f2faa72f3609741f83554b914c [file] [log] [blame]
swissChili682e7bc2021-12-07 09:04:54 -08001#include "Evaluator.h"
swissChili07d325f2021-12-08 20:02:05 -08002#include "Function.h"
3#include "Matcher.h"
4#include "VarContext.h"
swissChili682e7bc2021-12-07 09:04:54 -08005
swissChili07d325f2021-12-08 20:02:05 -08006#include <QDebug>
7
8RuntimeResult::RuntimeResult(QList<Token> result)
9{
10 _result = result;
11}
12
13RuntimeResult::RuntimeResult(QString message)
14{
15 _errorMessage = message;
swissChili923bd532021-12-08 22:48:58 -080016 _success = false;
swissChili07d325f2021-12-08 20:02:05 -080017}
18
19bool RuntimeResult::success() const
20{
21 return _success;
22}
23
24QString RuntimeResult::message() const
25{
26 return _errorMessage;
27}
28
29QList<Token> RuntimeResult::result() const
30{
31 return _result;
32}
33
34RuntimeResult::operator QString() const
35{
36 return QString(_success) + " " + _errorMessage;
37}
38
swissChili323883d2022-02-20 16:35:23 -080039Evaluator::Evaluator()
40{
41}
42
swissChili07d325f2021-12-08 20:02:05 -080043void Evaluator::addFunction(Function func)
44{
45 _functions[func.name()] = func;
46}
47
48void Evaluator::clearFunction(QString name)
49{
50 _functions.remove(name);
51}
52
53RuntimeResult Evaluator::evaluate(AstNode node, VarContext ctx)
54{
55 if (node.isSym())
56 {
57 return RuntimeResult(QList<Token>{Token(node.symbol())});
58 }
59 else if (node.isIdent())
60 {
61 return RuntimeResult(QList<Token>{Token(node.name())});
62 }
swissChili1060c0e2021-12-09 09:46:42 -080063 else if (node.isInteger())
64 {
65 return RuntimeResult(QList<Token>{Token::fromInteger(node.integer())});
66 }
swissChili07d325f2021-12-08 20:02:05 -080067 else if (node.isVar())
68 {
69 if (!ctx.exists(node.name()) || ctx.exists(node.name()) != node.symbol())
70 return RuntimeResult("Variable " + node + " is not defined");
71
72 if (node.symbol() == 'e')
73 {
74 return RuntimeResult(ctx.expressionVar(node.name()));
75 }
76 else
77 {
78 return RuntimeResult(QList<Token>{
79 ctx.singleVar(node.name())
80 });
81 }
82 }
83 else if (node.isParen())
84 {
85 QList<Token> result;
86
87 for (const AstNode &n : node.parenContent())
88 {
89 RuntimeResult internalResult = evaluate(n, ctx);
90 if (!internalResult.success())
91 return internalResult;
92
93 result.append(internalResult.result());
94 }
95
96 return RuntimeResult(QList<Token>{
97 Token(result)
98 });
99 }
100 else if (node.isFunc())
101 {
102 QList<Token> args;
103
104 for (const AstNode &arg : node.funcArgs())
105 {
106 RuntimeResult internalResult = evaluate(arg, ctx);
107 if (!internalResult.success())
108 return internalResult;
109
110 args.append(internalResult.result());
111 }
112
113 return callFunction(node.name(), args);
114 }
115
116 return RuntimeResult("#TYPE_ERROR");
117}
118
119RuntimeResult Evaluator::callFunction(QString name, QList<Token> args)
120{
121 if (!_functions.contains(name))
122 return RuntimeResult("Function " + name + " is not defined.");
123
124 Function func = _functions[name];
125
126 for (const Sentence &sentence : func.sentences())
127 {
128 MatchResult res = match(args, sentence.pattern(), VarContext());
129
130 if (!res.success)
131 continue;
132
swissChili323883d2022-02-20 16:35:23 -0800133 if (sentence.isExternal())
134 {
135 return RuntimeResult(sentence.externResult(args));
136 }
137
swissChili07d325f2021-12-08 20:02:05 -0800138 QList<Token> final;
139 for (const AstNode &node : sentence.result())
140 {
141 RuntimeResult argRes = evaluate(node, res.context);
142 if (!argRes.success())
143 return argRes;
144
145 final.append(argRes.result());
146 }
147
148 return RuntimeResult(final);
149 }
150
151 return RuntimeResult("Function " + name + " had no matching sentences for input");
152}