1/*-------------------------------------------------------------------------
2 * drawElements Quality Program Random Shader Generator
3 * ----------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Statements.
22 *//*--------------------------------------------------------------------*/
23
24#include "rsgStatement.hpp"
25#include "rsgExpressionGenerator.hpp"
26#include "rsgUtils.hpp"
27
28#include <typeinfo>
29
30using std::vector;
31
32namespace rsg
33{
34
35namespace
36{
37
38inline bool isCurrentTopStatementBlock (const GeneratorState& state)
39{
40	int stackDepth = state.getStatementDepth();
41	return dynamic_cast<const BlockStatement*>(state.getStatementStackEntry(stackDepth-1)) != DE_NULL;
42}
43
44template <class T> float		getWeight	(const GeneratorState& state)	{ return T::getWeight(state);	}
45template <class T> Statement*	create		(GeneratorState& state)			{ return new T(state);			}
46
47struct StatementSpec
48{
49	float		(*getWeight)		(const GeneratorState& state);
50	Statement*	(*create)			(GeneratorState& state);
51};
52
53const StatementSpec* chooseStatement (GeneratorState& state)
54{
55	static const StatementSpec statementSpecs[] =
56	{
57		{ getWeight<BlockStatement>,		create<BlockStatement>			},
58		{ getWeight<ExpressionStatement>,	create<ExpressionStatement>		},
59		{ getWeight<DeclarationStatement>,	create<DeclarationStatement>	},
60		{ getWeight<ConditionalStatement>,	create<ConditionalStatement>	}
61	};
62
63	float weights[DE_LENGTH_OF_ARRAY(statementSpecs)];
64
65	// Compute weights
66	float sum = 0.0f;
67	for (int ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(statementSpecs); ndx++)
68	{
69		weights[ndx] = statementSpecs[ndx].getWeight(state);
70		sum += weights[ndx];
71	}
72
73	DE_ASSERT(sum > 0.0f);
74
75	// Random number in range
76	float p = state.getRandom().getFloat(0.0f, sum);
77
78	const StatementSpec* spec			= DE_NULL;
79	const StatementSpec* lastNonZero	= DE_NULL;
80
81	// Find element in that point
82	sum = 0.0f;
83	for (int ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(statementSpecs); ndx++)
84	{
85		sum += weights[ndx];
86		if (p < sum)
87		{
88			spec = &statementSpecs[ndx];
89			break;
90		}
91		else if (weights[ndx] > 0.0f)
92			lastNonZero = &statementSpecs[ndx];
93	}
94
95	if (!spec)
96		spec = lastNonZero;
97
98	return spec;
99}
100
101Statement* createStatement (GeneratorState& state)
102{
103	return chooseStatement(state)->create(state);
104}
105
106} // anonymous
107
108Statement::Statement (void)
109{
110}
111
112Statement::~Statement (void)
113{
114}
115
116ExpressionStatement::ExpressionStatement (GeneratorState& state)
117	: m_expression(DE_NULL)
118{
119	ExpressionGenerator generator(state);
120	m_expression = generator.generate(ValueRange(VariableType(VariableType::TYPE_VOID)));
121}
122
123ExpressionStatement::~ExpressionStatement (void)
124{
125	delete m_expression;
126}
127
128float ExpressionStatement::getWeight (const GeneratorState& state)
129{
130	DE_UNREF(state);
131	return 1.0f;
132}
133
134void ExpressionStatement::execute (ExecutionContext& execCtx) const
135{
136	m_expression->evaluate(execCtx);
137}
138
139BlockStatement::BlockStatement (GeneratorState& state)
140{
141	init(state);
142}
143
144void BlockStatement::init (GeneratorState& state)
145{
146	// Select number of children statements to construct
147	m_numChildrenToCreate = state.getRandom().getInt(0, state.getShaderParameters().maxStatementsPerBlock);
148
149	// Push scope
150	state.getVariableManager().pushVariableScope(m_scope);
151}
152
153BlockStatement::~BlockStatement (void)
154{
155	for (vector<Statement*>::iterator i = m_children.begin(); i != m_children.end(); i++)
156		delete *i;
157	m_children.clear();
158}
159
160void BlockStatement::addChild (Statement* statement)
161{
162	try
163	{
164		m_children.push_back(statement);
165	}
166	catch (const std::exception&)
167	{
168		delete statement;
169		throw;
170	}
171}
172
173Statement* BlockStatement::createNextChild (GeneratorState& state)
174{
175	if ((int)m_children.size() < m_numChildrenToCreate)
176	{
177		// Select and create a new child
178		Statement* child = createStatement(state);
179		addChild(child);
180		return child;
181	}
182	else
183	{
184		// Done, pop scope
185		state.getVariableManager().popVariableScope();
186		return DE_NULL;
187	}
188}
189
190float BlockStatement::getWeight (const GeneratorState& state)
191{
192	if (state.getStatementDepth()+1 < state.getShaderParameters().maxStatementDepth)
193	{
194		if (isCurrentTopStatementBlock(state))
195			return 0.2f; // Low probability for anonymous blocks.
196		else
197			return 1.0f;
198	}
199	else
200		return 0.0f;
201}
202
203void BlockStatement::tokenize (GeneratorState& state, TokenStream& str) const
204{
205	str << Token::LEFT_BRACE << Token::NEWLINE << Token::INDENT_INC;
206
207	for (vector<Statement*>::const_reverse_iterator i = m_children.rbegin(); i != m_children.rend(); i++)
208		(*i)->tokenize(state, str);
209
210	str << Token::INDENT_DEC << Token::RIGHT_BRACE << Token::NEWLINE;
211}
212
213void BlockStatement::execute (ExecutionContext& execCtx) const
214{
215	for (vector<Statement*>::const_reverse_iterator i = m_children.rbegin(); i != m_children.rend(); i++)
216		(*i)->execute(execCtx);
217}
218
219void ExpressionStatement::tokenize (GeneratorState& state, TokenStream& str) const
220{
221	DE_ASSERT(m_expression);
222	m_expression->tokenize(state, str);
223	str << Token::SEMICOLON << Token::NEWLINE;
224}
225
226namespace
227{
228
229inline bool canDeclareVariable (const Variable* variable)
230{
231	return variable->getStorage() == Variable::STORAGE_LOCAL;
232}
233
234bool hasDeclarableVars (const VariableManager& varMgr)
235{
236	const vector<Variable*>& liveVars = varMgr.getLiveVariables();
237	for (vector<Variable*>::const_iterator i = liveVars.begin(); i != liveVars.end(); i++)
238	{
239		if (canDeclareVariable(*i))
240			return true;
241	}
242	return false;
243}
244
245} // anonymous
246
247DeclarationStatement::DeclarationStatement (GeneratorState& state, Variable* variable)
248	: m_variable	(DE_NULL)
249	, m_expression	(DE_NULL)
250{
251	if (variable == DE_NULL)
252	{
253		// Choose random
254		// \todo [2011-02-03 pyry] Allocate a new here?
255		// \todo [2011-05-26 pyry] Weights?
256		const vector<Variable*>&	liveVars = state.getVariableManager().getLiveVariables();
257		vector<Variable*>			candidates;
258
259		for (vector<Variable*>::const_iterator i = liveVars.begin(); i != liveVars.end(); i++)
260		{
261			if (canDeclareVariable(*i))
262				candidates.push_back(*i);
263		}
264
265		variable = state.getRandom().choose<Variable*>(candidates.begin(), candidates.end());
266	}
267
268	DE_ASSERT(variable);
269	m_variable = variable;
270
271	const ValueEntry* value = state.getVariableManager().getValue(variable);
272
273	bool createInitializer = false;
274
275	switch (m_variable->getStorage())
276	{
277		case Variable::STORAGE_CONST:
278			DE_ASSERT(value);
279			createInitializer = true;
280			break;
281
282		case Variable::STORAGE_LOCAL:
283			// \note Currently booleans are always treated as not having undefined range and thus
284			//       initializer is always created.
285			createInitializer = value && !isUndefinedValueRange(value->getValueRange());
286			break;
287
288		default:
289			createInitializer = false;
290			break;
291	}
292
293	if (createInitializer)
294	{
295		ExpressionGenerator generator(state);
296
297		// Take copy of value range for generating initializer expression
298		ValueRange valueRange = value->getValueRange();
299
300		// Declare (removes value entry)
301		state.getVariableManager().declareVariable(variable);
302
303		bool isConst = m_variable->getStorage() == Variable::STORAGE_CONST;
304
305		if (isConst)
306			state.pushExpressionFlags(state.getExpressionFlags() | CONST_EXPR);
307
308		m_expression = generator.generate(valueRange, 1);
309
310		if (isConst)
311			state.popExpressionFlags();
312	}
313	else
314		state.getVariableManager().declareVariable(variable);
315}
316
317DeclarationStatement::~DeclarationStatement (void)
318{
319	delete m_expression;
320}
321
322float DeclarationStatement::getWeight (const GeneratorState& state)
323{
324	if (!hasDeclarableVars(state.getVariableManager()))
325		return 0.0f;
326
327	if (!isCurrentTopStatementBlock(state))
328		return 0.0f;
329
330	return state.getProgramParameters().declarationStatementBaseWeight;
331}
332
333void DeclarationStatement::tokenize (GeneratorState& state, TokenStream& str) const
334{
335	m_variable->tokenizeDeclaration(state, str);
336
337	if (m_expression)
338	{
339		str << Token::EQUAL;
340		m_expression->tokenize(state, str);
341	}
342
343	str << Token::SEMICOLON << Token::NEWLINE;
344}
345
346void DeclarationStatement::execute (ExecutionContext& execCtx) const
347{
348	if (m_expression)
349	{
350		m_expression->evaluate(execCtx);
351		execCtx.getValue(m_variable) = m_expression->getValue().value();
352	}
353}
354
355ConditionalStatement::ConditionalStatement (GeneratorState&)
356	: m_condition		(DE_NULL)
357	, m_trueStatement	(DE_NULL)
358	, m_falseStatement	(DE_NULL)
359{
360}
361
362ConditionalStatement::~ConditionalStatement (void)
363{
364	delete m_condition;
365	delete m_trueStatement;
366	delete m_falseStatement;
367}
368
369bool ConditionalStatement::isElseBlockRequired (const GeneratorState& state) const
370{
371	// If parent is conditional statement with else block and this is the true statement,
372	// else block must be generated or otherwise parent "else" will end up parsed as else statement for this if.
373	const ConditionalStatement*	curChild	= this;
374	int							curStackNdx	= state.getStatementDepth()-2;
375
376	while (curStackNdx >= 0)
377	{
378		const ConditionalStatement* curParent = dynamic_cast<const ConditionalStatement*>(state.getStatementStackEntry(curStackNdx));
379
380		if (!curParent)
381			break; // Not a conditional statement - can end search here.
382
383		if (curChild == curParent->m_trueStatement && curParent->m_falseStatement)
384			return true; // Else block is mandatory.
385
386		// Continue search.
387		curChild	 = curParent;
388		curStackNdx	-= 1;
389	}
390
391	return false;
392}
393
394Statement* ConditionalStatement::createNextChild (GeneratorState& state)
395{
396	// If has neither true or false statements, choose randomly whether to create false block.
397	if (!m_falseStatement && !m_trueStatement && (isElseBlockRequired(state) || state.getRandom().getBool()))
398	{
399		// Construct false statement
400		state.getVariableManager().pushValueScope(m_conditionalScope);
401		m_falseStatement = createStatement(state);
402
403		return m_falseStatement;
404	}
405	else if (!m_trueStatement)
406	{
407		if (m_falseStatement)
408		{
409			// Pop previous value scope.
410			state.getVariableManager().popValueScope();
411			m_conditionalScope.clear();
412		}
413
414		// Construct true statement
415		state.getVariableManager().pushValueScope(m_conditionalScope);
416		m_trueStatement = createStatement(state);
417
418		return m_trueStatement;
419	}
420	else
421	{
422		// Pop conditional scope.
423		state.getVariableManager().popValueScope();
424		m_conditionalScope.clear();
425
426		// Create condition
427		DE_ASSERT(!m_condition);
428
429		ExpressionGenerator generator(state);
430
431		ValueRange range = ValueRange(VariableType::getScalarType(VariableType::TYPE_BOOL));
432		range.getMin().asBool() = false;
433		range.getMax().asBool() = true;
434
435		m_condition = generator.generate(range, 1);
436
437		return DE_NULL; // Done with this statement
438	}
439}
440
441namespace
442{
443
444bool isBlockStatement (const Statement* statement)
445{
446	return dynamic_cast<const BlockStatement*>(statement) != DE_NULL;
447}
448
449bool isConditionalStatement (const Statement* statement)
450{
451	return dynamic_cast<const ConditionalStatement*>(statement) != DE_NULL;
452}
453
454} // anonymous
455
456void ConditionalStatement::tokenize (GeneratorState& state, TokenStream& str) const
457{
458	DE_ASSERT(m_condition && m_trueStatement);
459
460	// if (condition)
461	str << Token::IF << Token::LEFT_PAREN;
462	m_condition->tokenize(state, str);
463	str << Token::RIGHT_PAREN << Token::NEWLINE;
464
465	// Statement executed if true
466	if (!isBlockStatement(m_trueStatement))
467	{
468		str << Token::INDENT_INC;
469		m_trueStatement->tokenize(state, str);
470		str << Token::INDENT_DEC;
471	}
472	else
473		m_trueStatement->tokenize(state, str);
474
475	if (m_falseStatement)
476	{
477		str << Token::ELSE;
478
479		if (isConditionalStatement(m_falseStatement))
480		{
481			m_falseStatement->tokenize(state, str);
482		}
483		else if (isBlockStatement(m_falseStatement))
484		{
485			str << Token::NEWLINE;
486			m_falseStatement->tokenize(state, str);
487		}
488		else
489		{
490			str << Token::NEWLINE << Token::INDENT_INC;
491			m_falseStatement->tokenize(state, str);
492			str << Token::INDENT_DEC;
493		}
494	}
495}
496
497void ConditionalStatement::execute (ExecutionContext& execCtx) const
498{
499	// Evaluate condition
500	m_condition->evaluate(execCtx);
501
502	ExecMaskStorage	maskStorage; // Value might change when we are evaluating true block so we have to take a copy.
503	ExecValueAccess	trueMask	= maskStorage.getValue();
504
505	trueMask = m_condition->getValue().value();
506
507	// And mask, execute true statement and pop
508	execCtx.andExecutionMask(trueMask);
509	m_trueStatement->execute(execCtx);
510	execCtx.popExecutionMask();
511
512	if (m_falseStatement)
513	{
514		// Construct negated mask, execute false statement and pop
515		ExecMaskStorage tmp;
516		ExecValueAccess	falseMask = tmp.getValue();
517
518		for (int i = 0; i < EXEC_VEC_WIDTH; i++)
519			falseMask.asBool(i) = !trueMask.asBool(i);
520
521		execCtx.andExecutionMask(falseMask);
522		m_falseStatement->execute(execCtx);
523		execCtx.popExecutionMask();
524	}
525}
526
527float ConditionalStatement::getWeight (const GeneratorState& state)
528{
529	if (!state.getProgramParameters().useConditionals)
530		return 0.0f;
531
532	int availableLevels = state.getShaderParameters().maxStatementDepth - state.getStatementDepth();
533	return (availableLevels > 1) ? 1.0f : 0.0f;
534}
535
536AssignStatement::AssignStatement (const Variable* variable, Expression* value)
537	: m_variable	(variable)
538	, m_valueExpr	(value)	// \note Takes ownership of value
539{
540}
541
542AssignStatement::AssignStatement (GeneratorState& state, const Variable* variable, ConstValueRangeAccess valueRange)
543	: m_variable	(variable)
544	, m_valueExpr	(DE_NULL)
545{
546	// Generate random value
547	ExpressionGenerator generator(state);
548	m_valueExpr = generator.generate(valueRange, 1);
549}
550
551AssignStatement::~AssignStatement (void)
552{
553	delete m_valueExpr;
554}
555
556void AssignStatement::tokenize (GeneratorState& state, TokenStream& str) const
557{
558	str << Token(m_variable->getName()) << Token::EQUAL;
559	m_valueExpr->tokenize(state, str);
560	str << Token::SEMICOLON << Token::NEWLINE;
561}
562
563void AssignStatement::execute (ExecutionContext& execCtx) const
564{
565	m_valueExpr->evaluate(execCtx);
566	assignMasked(execCtx.getValue(m_variable), m_valueExpr->getValue(), execCtx.getExecutionMask());
567}
568
569} // rsg
570