File: RandomRangeExpression.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 (108 lines) | stat: -rw-r--r-- 3,192 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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

#include "RandomRangeExpression.h"

#include "actions/expression/TypeDefinition.h"
#include "utils/RandomRange.h"

namespace actions {
namespace expression {
namespace nodes {

namespace {

template <typename T>
Value executeHelper(const Value& leftVal, const Value& rightVal)
{
	auto leftContentVal = leftVal.get<T>();
	auto rightContentVal = rightVal.get<T>();

	if (leftContentVal == rightContentVal) {
		// no need to do random stuff here
		return Value(rightContentVal);
	}

	if (rightContentVal < leftContentVal) {
		// We can fix this issue
		std::swap(leftContentVal, rightContentVal);
	}

	// Might be a bit inefficient not to cache this somehow but the bounds can be dynamic
	return Value(util::UniformRange<T>(leftContentVal, rightContentVal).next());
}
} // namespace

RandomRangeExpression::RandomRangeExpression(antlr4::Token* token,
	std::shared_ptr<AbstractExpression> leftExpression,
	std::shared_ptr<AbstractExpression> rightExpression)
	: AbstractExpression(token), m_leftExpression(std::move(leftExpression)),
	  m_rightExpression(std::move(rightExpression))
{
}
RandomRangeExpression::~RandomRangeExpression() = default;

Value RandomRangeExpression::execute(const ProgramVariables& variables) const
{
	const auto leftVal = m_leftExpression->execute(variables);
	const auto rightVal = m_rightExpression->execute(variables);

	if (leftVal.getType() == ValueType::Integer) {
		return executeHelper<int>(leftVal, rightVal);
	} else {
		return executeHelper<float>(leftVal, rightVal);
	}
}
bool RandomRangeExpression::validate(antlr4::Parser* parser, const ParseContext& context)
{
	bool valid = true;

	valid &= m_leftExpression->validate(parser, context);
	valid &= m_rightExpression->validate(parser, context);

	if (!valid) {
		// Exit early if there were errors since the values below are meaningless otherwise
		return false;
	}

	const auto leftType = m_leftExpression->getExpressionType();
	const auto rightType = m_rightExpression->getExpressionType();

	const auto& leftTypedef = TypeDefinition::forValueType(leftType);
	const auto& rightTypedef = TypeDefinition::forValueType(rightType);

	// Both values must be the same
	if (leftType != rightType) {
		parser->notifyErrorListeners(m_rightExpression->getToken(),
			"Inconsistent types for random range. Must be the same but got <" + leftTypedef.getName() + "> and <" +
				rightTypedef.getName() + ">.",
			nullptr);
		return false;
	}

	// And we only support floats or integers
	if (leftType != ValueType::Float && leftType != ValueType::Integer) {
		parser->notifyErrorListeners(m_leftExpression->getToken(),
			"Invalid parameter type for random range. Must be <Float> or <Integer> but got <" + leftTypedef.getName() +
				">.",
			nullptr);
		return false;
	}

	// Everything is fine.
	return true;
}
ValueType RandomRangeExpression::determineReturnType() const
{
	// Return type is the same as the contained return types
	return m_leftExpression->getExpressionType();
}
void RandomRangeExpression::validationDone()
{
	AbstractExpression::validationDone();

	m_leftExpression->validationDone();
	m_rightExpression->validationDone();
}

} // namespace nodes
} // namespace expression
} // namespace actions