File: FunctionManager.cpp

package info (click to toggle)
freespace2 24.2.0%2Brepack-3
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 43,740 kB
  • sloc: cpp: 595,005; ansic: 21,741; python: 1,174; sh: 457; makefile: 243; xml: 181
file content (90 lines) | stat: -rw-r--r-- 2,559 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

#include "FunctionManager.h"

#include "TypeDefinition.h"

#include "math/vecmat.h"

namespace actions {
namespace expression {
namespace {
template <typename T>
Value value_plus(const SCP_vector<Value>& parameters)
{
	return Value(parameters[0].get<T>() + parameters[1].get<T>());
}
template <typename T>
Value value_minus(const SCP_vector<Value>& parameters)
{
	return Value(parameters[0].get<T>() - parameters[1].get<T>());
}
} // namespace

const FunctionManager& FunctionManager::instance()
{
	static const FunctionManager manager;
	return manager;
}
void FunctionManager::addOperator(const SCP_string& name,
	std::initializer_list<ValueType> parameterTypes,
	ValueType returnType,
	FunctionImplementation implementation)
{
	m_operators[name].push_back({name, parameterTypes, returnType, std::move(implementation)});
}
const FunctionDefinition* FunctionManager::findOperator(const SCP_string& name,
	const SCP_vector<ValueType>& parameters) const
{
	const auto iter = m_operators.find(name);

	if (iter == m_operators.end()) {
		return nullptr;
	}

	// Prefer exact matches
	for (const auto& funcDef : iter->second) {
		if (funcDef.parameterTypes == parameters) {
			return &funcDef;
		}
	}

	// Now check if there are matches with implicit conversions
	for (const auto& funcDef : iter->second) {
		// Reject functions with different amount of elements
		if (funcDef.parameterTypes.size() != parameters.size()) {
			continue;
		}

		auto funcParamIter = funcDef.parameterTypes.cbegin();
		auto actualParamIter = parameters.cbegin();

		bool match = true;
		for (; funcParamIter != funcDef.parameterTypes.cend(); ++funcParamIter, ++actualParamIter) {
			if (!checkTypeWithImplicitConversion(*actualParamIter, *funcParamIter)) {
				// Also doesn't match with implicit conversions
				match = false;
				break;
			}
		}

		if (match) {
			return &funcDef;
		}
	}

	return nullptr;
}

FunctionManager::FunctionManager()
{
	addOperator("+", {ValueType::Integer, ValueType::Integer}, ValueType::Integer, value_plus<int>);
	addOperator("+", {ValueType::Float, ValueType::Float}, ValueType::Float, value_plus<float>);
	addOperator("+", {ValueType::Vector, ValueType::Vector}, ValueType::Vector, value_plus<vec3d>);

	addOperator("-", {ValueType::Integer, ValueType::Integer}, ValueType::Integer, value_minus<int>);
	addOperator("-", {ValueType::Float, ValueType::Float}, ValueType::Float, value_minus<float>);
	addOperator("-", {ValueType::Vector, ValueType::Vector}, ValueType::Vector, value_minus<vec3d>);
}

} // namespace expression
} // namespace actions