Add evaluator
diff --git a/.gitignore b/.gitignore
index 82ffdc1..e37d10e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
 cmake-build-*
 *.user
 build
+.cache
diff --git a/Evaluator.cpp b/Evaluator.cpp
index 70ed91b..e4e5d6f 100644
--- a/Evaluator.cpp
+++ b/Evaluator.cpp
@@ -1,2 +1,138 @@
 #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;
+}
+
+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;
+}
+
+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.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;
+
+		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");
+}
diff --git a/Evaluator.h b/Evaluator.h
index 3eaef52..62fd23f 100644
--- a/Evaluator.h
+++ b/Evaluator.h
@@ -1,5 +1,39 @@
 #pragma once
 
+#include <QMap>
+
+#include "Token.h"
+#include "AstNode.h"
+#include "Function.h"
+#include "VarContext.h"
+
+class RuntimeResult
+{
+public:
+	RuntimeResult(QList<Token> result);
+	RuntimeResult(QString message);
+	
+	bool success() const;
+	QString message() const;
+	QList<Token> result() const;
+
+	operator QString() const;
+	
+private:
+	bool _success = true;
+	QString _errorMessage;
+	QList<Token> _result;
+};
+
 class Evaluator {
 public:
+	Evaluator() = default;
+
+	void addFunction(Function func);
+	void clearFunction(QString name);
+	RuntimeResult evaluate(AstNode node, VarContext ctx);
+	RuntimeResult callFunction(QString name, QList<Token> args);
+
+private:
+	QMap<QString, Function> _functions;
 };
diff --git a/Matcher.cpp b/Matcher.cpp
index 42fd155..460253a 100644
--- a/Matcher.cpp
+++ b/Matcher.cpp
@@ -9,7 +9,7 @@
         return MatchResult{true, context};
     }
 
-    if (pattern.empty() && !data.empty())
+    if ((pattern.empty() && !data.empty()) || (data.empty() && !pattern.empty()))
     {
         return MatchResult{false, context};
     }
@@ -105,7 +105,8 @@
 
             case 'e':
                 // Now this is tricky
-                for (int matchSyms = 1; matchSyms < data.length(); matchSyms++)
+                // TODO: Optimize this to check if there is an obvious length that this expression has to be
+                for (int matchSyms = 1; matchSyms <= data.length(); matchSyms++)
                 {
                     QList<Token> slice = listSlice(data, 0, matchSyms);
                     VarContext newContext = context;
diff --git a/Matcher.h b/Matcher.h
index 24fc795..c417191 100644
--- a/Matcher.h
+++ b/Matcher.h
@@ -38,6 +38,9 @@
 {
     QList<T> prime;
 
+	if (from >= list.length())
+		return prime;
+
     // I guess we'll just panic if it's too long
     // TODO: ERROR HANDLING
     for (int i = 0; i < to - from; i++)
diff --git a/Token.cpp b/Token.cpp
index 56c32a9..ac104a4 100644
--- a/Token.cpp
+++ b/Token.cpp
@@ -1,3 +1,153 @@
 #include "Token.h"
+#include "AstNode.h"
 
-// Nothing, aparently
+template class TokenBase<Token>;
+
+// This is kind of ugly and breaks separation of concerns; but if I don't do
+// this I have to define everything in headers which is worse.
+template class TokenBase<AstNode>;
+
+template <typename T>
+TokenBase<T>::TokenBase(const T &other)
+{
+    _type = other._type;
+    _stringVal = other._stringVal;
+    _listVal = other._listVal;
+    _charVal = other._charVal;
+}
+
+template <typename T>
+TokenBase<T>::TokenBase(QChar symbol)
+{
+    _type = SYM;
+    _charVal = symbol;
+}
+
+template <typename T>
+TokenBase<T>::TokenBase(QString identifier)
+{
+    _type = IDENT;
+    _stringVal = identifier;
+}
+
+template <typename T>
+TokenBase<T>::TokenBase(QList<T> parenthesized)
+{
+    _type = PAREN;
+    _listVal = std::move(parenthesized);
+}
+
+template <typename T>
+TokenBase<T>::TokenBase(char varType, const QString name)
+{
+    _type = VAR;
+    _charVal = varType;
+    _stringVal = name;
+}
+
+template <typename T>
+bool TokenBase<T>::isSym() const
+{
+    return _type == SYM;
+}
+
+template <typename T>
+bool TokenBase<T>::isIdent() const
+{
+    return _type == IDENT;
+}
+
+template <typename T>
+bool TokenBase<T>::isParen() const
+{
+    return _type == PAREN;
+}
+template <typename T>
+bool TokenBase<T>::isVar() const
+{
+    return _type == VAR;
+}
+
+template <typename T>
+TokenBase<T>::TokenBase() : TokenBase("Null")
+{
+}
+
+template <typename T>
+bool TokenBase<T>::operator==(const T &other) const
+{
+    return _type == other._type && _stringVal == other._stringVal && _charVal == other._charVal && _listVal == other._listVal;
+}
+
+template <typename T>
+QList<T> TokenBase<T>::parenContent()
+{
+    if (isParen())
+    {
+        return _listVal;
+    }
+    else
+    {
+        return {};
+    }
+}
+
+template <typename T>
+char TokenBase<T>::varType() const
+{
+    return _charVal.toLatin1();
+}
+
+template <typename T>
+const QString &TokenBase<T>::name() const
+{
+    return _stringVal;
+}
+
+template <typename T>
+bool TokenBase<T>::operator!=(const T &other) const
+{
+    return !(this->operator==(other));
+}
+
+template <typename T>
+TokenBase<T>::operator QString() const
+{
+    if (isIdent())
+        return _stringVal;
+    if (isSym())
+        return _charVal;
+    if (isVar())
+        return QString(_charVal) + "." + _stringVal;
+    if (isParen())
+    {
+        QStringList parts;
+        for (const T &tok : _listVal)
+        {
+            parts.append(static_cast<QString>(tok));
+        }
+
+        return "(" + parts.join(" ") + ")";
+    }
+
+    return "Null";
+}
+
+template <typename T>
+int TokenBase<T>::type() const
+{
+    return _type;
+}
+
+template <typename T>
+QString TokenBase<T>::typeToString(int type)
+{
+    static const QString typeNames[] = {"SYMBOL", "IDENT", "PAREN", "VAR"};
+    return typeNames[type];
+}
+
+template <typename T>
+QChar TokenBase<T>::symbol() const
+{
+    return _charVal;
+}
diff --git a/Token.h b/Token.h
index dfa0223..75c4455 100644
--- a/Token.h
+++ b/Token.h
@@ -58,148 +58,3 @@
 };
 
 using LTok = QList<Token>;
-
-template <typename T>
-TokenBase<T>::TokenBase(const T &other)
-{
-    _type = other._type;
-    _stringVal = other._stringVal;
-    _listVal = other._listVal;
-    _charVal = other._charVal;
-}
-
-template <typename T>
-TokenBase<T>::TokenBase(QChar symbol)
-{
-    _type = SYM;
-    _charVal = symbol;
-}
-
-template <typename T>
-TokenBase<T>::TokenBase(QString identifier)
-{
-    _type = IDENT;
-    _stringVal = identifier;
-}
-
-template <typename T>
-TokenBase<T>::TokenBase(QList<T> parenthesized)
-{
-    _type = PAREN;
-    _listVal = std::move(parenthesized);
-}
-
-template <typename T>
-TokenBase<T>::TokenBase(char varType, const QString name)
-{
-    _type = VAR;
-    _charVal = varType;
-    _stringVal = name;
-}
-
-template <typename T>
-bool TokenBase<T>::isSym() const
-{
-    return _type == SYM;
-}
-
-template <typename T>
-bool TokenBase<T>::isIdent() const
-{
-    return _type == IDENT;
-}
-
-template <typename T>
-bool TokenBase<T>::isParen() const
-{
-    return _type == PAREN;
-}
-template <typename T>
-bool TokenBase<T>::isVar() const
-{
-    return _type == VAR;
-}
-
-template <typename T>
-TokenBase<T>::TokenBase() : TokenBase("Null")
-{
-}
-
-template <typename T>
-bool TokenBase<T>::operator==(const T &other) const
-{
-    return _type == other._type && _stringVal == other._stringVal && _charVal == other._charVal && _listVal == other._listVal;
-}
-
-template <typename T>
-QList<T> TokenBase<T>::parenContent()
-{
-    if (isParen())
-    {
-        return _listVal;
-    }
-    else
-    {
-        return {};
-    }
-}
-
-template <typename T>
-char TokenBase<T>::varType() const
-{
-    return _charVal.toLatin1();
-}
-
-template <typename T>
-const QString &TokenBase<T>::name() const
-{
-    return _stringVal;
-}
-
-template <typename T>
-bool TokenBase<T>::operator!=(const T &other) const
-{
-    return !(this->operator==(other));
-}
-
-template <typename T>
-TokenBase<T>::operator QString() const
-{
-    if (isIdent())
-        return _stringVal;
-    if (isSym())
-        return _charVal;
-    if (isVar())
-        return QString(_charVal) + "." + _stringVal;
-    if (isParen())
-    {
-        QStringList parts;
-        for (const T &tok : _listVal)
-        {
-            parts.append(static_cast<QString>(tok));
-        }
-
-        return "(" + parts.join(" ") + ")";
-    }
-
-    return "Null";
-}
-
-template <typename T>
-int TokenBase<T>::type() const
-{
-    return _type;
-}
-
-template <typename T>
-QString TokenBase<T>::typeToString(int type)
-{
-    static const QString typeNames[] = {"SYMBOL", "IDENT", "PAREN", "VAR"};
-    return typeNames[type];
-}
-
-template <typename T>
-QChar TokenBase<T>::symbol() const
-{
-    return _charVal;
-}
diff --git a/main.cpp b/main.cpp
index 25c4504..2d40231 100644
--- a/main.cpp
+++ b/main.cpp
@@ -5,9 +5,73 @@
 #include "Token.h"
 #include "AstNode.h"
 #include "Parser.h"
+#include "Evaluator.h"
+#include "VarContext.h"
 
 int g_numFailed = 0;
 
+void testEval(QString function, QString expression, QString expected)
+{
+	Evaluator eval;
+	Parser funcParser(function),
+		exprParser(expression),
+		resParser(expected);
+
+	Function func;
+
+	QList<AstNode> expr = exprParser.parseMany<AstNode>();
+	QList<Token> res = resParser.parseMany<Token>();
+
+	QList<Token> result;
+
+	exprParser.skip();
+	resParser.skip();
+	while (funcParser.parseFunctionDefinition(&func))
+	{
+		eval.addFunction(func);
+	}
+
+	funcParser.skip();
+
+	if (!exprParser.atEnd() || !resParser.atEnd() || !funcParser.atEnd())
+	{
+        g_numFailed++;
+        qDebug() << "\n\033[31mTEST FAILS:\033[0m";
+		qDebug() << "Failed to fully parse expression, function or result";
+		qDebug() << function << expression << expected;
+
+		goto end;
+	}
+
+	for (const AstNode &node : expr)
+	{
+		RuntimeResult rr = eval.evaluate(node, VarContext());
+
+		if (!rr.success())
+		{
+			g_numFailed++;
+			qDebug() << "\n\033[31mTEST FAILS:\033[0m";
+			qDebug() << "Runtime error while evaluating" << node;
+			qDebug() << rr;
+
+			goto end;
+		}
+
+		result.append(rr.result());
+	}
+
+	if (result != res)
+	{
+		g_numFailed++;
+		qDebug() << "\n\033[31mTEST FAILS:\033[0m";
+		qDebug() << "Expected result" << res;
+		qDebug() << "Got" << result;
+	}
+
+end:
+	qDebug() << "\033[36mEvaluate\033[0m" << function << expression << "->" << result;
+}
+
 void testMatch(const QString &test, bool shouldBe, const MatchResult &result)
 {
     if (result.success != shouldBe)
@@ -30,7 +94,8 @@
     Parser dataParser(data),
         patternParser(pattern);
 
-    testMatch(pattern + " = " + data, shouldBe, match(dataParser.parseMany<Token>(), patternParser.parseMany<Token>(), VarContext()));
+    testMatch(pattern + " = " + data, shouldBe,
+			  match(dataParser.parseMany<Token>(), patternParser.parseMany<Token>(), VarContext()));
 }
 
 void testParseAst(QString string)
@@ -114,6 +179,7 @@
     // testMatch("(y)f Middle-stuff y", "(s.a) e.Middle s.a");
 
     testMatch("(a)", "(a)");
+	testMatch("hello", "s.A e.Rest");
 }
 
 void testAllParses()
@@ -135,7 +201,12 @@
 void testAllFunctionDefs()
 {
     testParseFunc("Test { = HI; }");
-    testParseFunc("Palindrome { = T; s.A = T; s.A s.A = T; s.A e.Middle s.A = <Palindrome e.Middle>; } ");
+    testParseFunc("Palindrome { = T; s.A = T; s.A s.A = T; s.A e.Middle s.A = <Palindrome e.Middle>; e.Ignored = F; } ");
+}
+
+void testAllEvals()
+{
+	testEval("First {s.A e.Rest = s.A;}", "<First hello>", "h");
 }
 
 int main(int argc, char *argv[])
@@ -147,6 +218,8 @@
     testAllParses();
     qDebug() << "";
     testAllFunctionDefs();
+	qDebug() << "";
+	testAllEvals();
 
     qDebug() << "";
     return testResults();