+ r_constant = false;
+}
+
+void ConstantFolder::visit(Swizzle &swizzle)
+{
+ TraversingVisitor::visit(swizzle);
+ r_constant = false;
+}
+
+void ConstantFolder::visit(UnaryExpression &unary)
+{
+ TraversingVisitor::visit(unary);
+ bool can_fold = r_constant;
+ r_constant = false;
+ if(!can_fold)
+ return;
+
+ BasicTypeDeclaration::Kind kind = get_value_kind(r_constant_value);
+
+ char oper = unary.oper->token[0];
+ char oper2 = unary.oper->token[1];
+ if(oper=='!')
+ {
+ if(kind==BasicTypeDeclaration::BOOL)
+ set_result(!r_constant_value.value<bool>());
+ }
+ else if(oper=='~')
+ {
+ if(kind==BasicTypeDeclaration::INT)
+ set_result(~r_constant_value.value<int>());
+ }
+ else if(oper=='-' && !oper2)
+ {
+ if(kind==BasicTypeDeclaration::INT)
+ set_result(-r_constant_value.value<int>());
+ else if(kind==BasicTypeDeclaration::FLOAT)
+ set_result(-r_constant_value.value<float>());
+ }
+}
+
+void ConstantFolder::visit(BinaryExpression &binary)
+{
+ visit(binary.left);
+ bool left_constant = r_constant;
+ bool left_iter_var = r_uses_iter_var;
+ Variant left_value = r_constant_value;
+ visit(binary.right);
+ if(left_iter_var)
+ r_uses_iter_var = true;
+
+ bool can_fold = (left_constant && r_constant);
+ r_constant = false;
+ if(!can_fold)
+ return;
+
+ BasicTypeDeclaration::Kind left_kind = get_value_kind(left_value);
+ BasicTypeDeclaration::Kind right_kind = get_value_kind(r_constant_value);
+ // Currently only expressions with both sides of equal types are handled.
+ if(left_kind!=right_kind)
+ return;
+
+ char oper = binary.oper->token[0];
+ char oper2 = binary.oper->token[1];
+ if(oper=='&' || oper=='|' || oper=='^')
+ {
+ if(oper2==oper && left_kind==BasicTypeDeclaration::BOOL)
+ set_result(evaluate_logical(oper, left_value.value<bool>(), r_constant_value.value<bool>()));
+ else if(!oper2 && left_kind==BasicTypeDeclaration::INT)
+ set_result(evaluate_logical(oper, left_value.value<int>(), r_constant_value.value<int>()));
+ }
+ else if((oper=='<' || oper=='>') && oper2!=oper)
+ {
+ if(left_kind==BasicTypeDeclaration::INT)
+ set_result(evaluate_relation(binary.oper->token, left_value.value<int>(), r_constant_value.value<int>()));
+ else if(left_kind==BasicTypeDeclaration::FLOAT)
+ set_result(evaluate_relation(binary.oper->token, left_value.value<float>(), r_constant_value.value<float>()));
+ }
+ else if((oper=='=' || oper=='!') && oper2=='=')
+ {
+ if(left_kind==BasicTypeDeclaration::INT)
+ set_result((left_value.value<int>()==r_constant_value.value<int>()) == (oper=='='));
+ if(left_kind==BasicTypeDeclaration::FLOAT)
+ set_result((left_value.value<float>()==r_constant_value.value<float>()) == (oper=='='));
+ }
+ else if(oper=='+' || oper=='-' || oper=='*' || oper=='/')
+ {
+ if(left_kind==BasicTypeDeclaration::INT)
+ set_result(evaluate_arithmetic(oper, left_value.value<int>(), r_constant_value.value<int>()));
+ else if(left_kind==BasicTypeDeclaration::FLOAT)
+ set_result(evaluate_arithmetic(oper, left_value.value<float>(), r_constant_value.value<float>()));
+ }
+ else if(oper=='%' || ((oper=='<' || oper=='>') && oper2==oper))
+ {
+ if(left_kind!=BasicTypeDeclaration::INT)
+ return;
+
+ if(oper=='%')
+ set_result(left_value.value<int>()%r_constant_value.value<int>());
+ else if(oper=='<')
+ set_result(left_value.value<int>()<<r_constant_value.value<int>());
+ else if(oper=='>')
+ set_result(left_value.value<int>()>>r_constant_value.value<int>());
+ }
+}
+
+void ConstantFolder::visit(Assignment &assign)
+{
+ TraversingVisitor::visit(assign);
+ r_constant = false;
+}
+
+void ConstantFolder::visit(TernaryExpression &ternary)
+{
+ TraversingVisitor::visit(ternary);
+ r_constant = false;
+}
+
+void ConstantFolder::visit(FunctionCall &call)
+{
+ TraversingVisitor::visit(call);
+ r_constant = false;