}
}
+template<typename T>
+T ConstantFolder::evaluate_int_special_op(char oper, T left, T right)
+{
+ switch(oper)
+ {
+ case '%': return left%right;
+ case '<': return left<<right;
+ case '>': return left>>right;
+ default: return T();
+ }
+}
+
+template<typename T>
+void ConstantFolder::convert_to_result(const Variant &value)
+{
+ if(value.check_type<bool>())
+ set_result(static_cast<T>(value.value<bool>()));
+ else if(value.check_type<int>())
+ set_result(static_cast<T>(value.value<int>()));
+ else if(value.check_type<float>())
+ set_result(static_cast<T>(value.value<float>()));
+}
+
void ConstantFolder::set_result(const Variant &value, bool literal)
{
r_constant_value = value;
}
else if(oper=='%' || ((oper=='<' || oper=='>') && oper2==oper))
{
- if(!left_value.check_type<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>());
+ if(left_value.check_type<int>())
+ set_result(evaluate_int_special_op(oper, left_value.value<int>(), r_constant_value.value<int>()));
}
}
void ConstantFolder::visit(FunctionCall &call)
{
+ if(call.constructor && call.type && call.arguments.size()==1)
+ {
+ const BasicTypeDeclaration *basic = dynamic_cast<const BasicTypeDeclaration *>(call.type);
+ if(basic)
+ {
+ call.arguments[0]->visit(*this);
+ bool can_fold = r_constant;
+ r_constant = false;
+ if(!can_fold)
+ return;
+
+ if(basic->kind==BasicTypeDeclaration::BOOL)
+ convert_to_result<bool>(r_constant_value);
+ else if(basic->kind==BasicTypeDeclaration::INT && basic->size==32)
+ convert_to_result<int>(r_constant_value);
+ else if(basic->kind==BasicTypeDeclaration::FLOAT && basic->size==32)
+ convert_to_result<float>(r_constant_value);
+
+ return;
+ }
+ }
+
TraversingVisitor::visit(call);
r_constant = false;
}