blob: b52b84322b1dc7f2faa72f3609741f83554b914c [file] [log] [blame]
#include "Evaluator.h"
#include "Function.h"
#include "Matcher.h"
#include "VarContext.h"
#include <QDebug>
RuntimeResult::RuntimeResult(QList<Token> result)
{
_result = result;
}
RuntimeResult::RuntimeResult(QString message)
{
_errorMessage = message;
_success = false;
}
bool RuntimeResult::success() const
{
return _success;
}
QString RuntimeResult::message() const
{
return _errorMessage;
}
QList<Token> RuntimeResult::result() const
{
return _result;
}
RuntimeResult::operator QString() const
{
return QString(_success) + " " + _errorMessage;
}
Evaluator::Evaluator()
{
}
void Evaluator::addFunction(Function func)
{
_functions[func.name()] = func;
}
void Evaluator::clearFunction(QString name)
{
_functions.remove(name);
}
RuntimeResult Evaluator::evaluate(AstNode node, VarContext ctx)
{
if (node.isSym())
{
return RuntimeResult(QList<Token>{Token(node.symbol())});
}
else if (node.isIdent())
{
return RuntimeResult(QList<Token>{Token(node.name())});
}
else if (node.isInteger())
{
return RuntimeResult(QList<Token>{Token::fromInteger(node.integer())});
}
else if (node.isVar())
{
if (!ctx.exists(node.name()) || ctx.exists(node.name()) != node.symbol())
return RuntimeResult("Variable " + node + " is not defined");
if (node.symbol() == 'e')
{
return RuntimeResult(ctx.expressionVar(node.name()));
}
else
{
return RuntimeResult(QList<Token>{
ctx.singleVar(node.name())
});
}
}
else if (node.isParen())
{
QList<Token> result;
for (const AstNode &n : node.parenContent())
{
RuntimeResult internalResult = evaluate(n, ctx);
if (!internalResult.success())
return internalResult;
result.append(internalResult.result());
}
return RuntimeResult(QList<Token>{
Token(result)
});
}
else if (node.isFunc())
{
QList<Token> args;
for (const AstNode &arg : node.funcArgs())
{
RuntimeResult internalResult = evaluate(arg, ctx);
if (!internalResult.success())
return internalResult;
args.append(internalResult.result());
}
return callFunction(node.name(), args);
}
return RuntimeResult("#TYPE_ERROR");
}
RuntimeResult Evaluator::callFunction(QString name, QList<Token> args)
{
if (!_functions.contains(name))
return RuntimeResult("Function " + name + " is not defined.");
Function func = _functions[name];
for (const Sentence &sentence : func.sentences())
{
MatchResult res = match(args, sentence.pattern(), VarContext());
if (!res.success)
continue;
if (sentence.isExternal())
{
return RuntimeResult(sentence.externResult(args));
}
QList<Token> final;
for (const AstNode &node : sentence.result())
{
RuntimeResult argRes = evaluate(node, res.context);
if (!argRes.success())
return argRes;
final.append(argRes.result());
}
return RuntimeResult(final);
}
return RuntimeResult("Function " + name + " had no matching sentences for input");
}