block.variables.clear();
}
+void VariableResolver::visit_and_replace(RefPtr<Expression> &expr)
+{
+ r_replacement_expr = 0;
+ expr->visit(*this);
+ if(r_replacement_expr)
+ expr = r_replacement_expr;
+ r_replacement_expr = 0;
+}
+
void VariableResolver::visit(VariableReference &var)
{
VariableDeclaration *declaration = 0;
{
/* The name refers to an interface block with an instance name rather
than a variable. Prepare a new syntax tree node accordingly. */
- r_iface_ref = new InterfaceBlockReference;
- r_iface_ref->source = var.source;
- r_iface_ref->line = var.line;
- r_iface_ref->name = var.name;
- r_iface_ref->declaration = i->second;
+ InterfaceBlockReference *iface_ref = new InterfaceBlockReference;
+ iface_ref->source = var.source;
+ iface_ref->line = var.line;
+ iface_ref->name = var.name;
+ iface_ref->declaration = i->second;
+ r_replacement_expr = iface_ref;
}
else
{
void VariableResolver::visit(MemberAccess &memacc)
{
- r_iface_ref = 0;
- memacc.left->visit(*this);
- if(r_iface_ref)
- memacc.left = r_iface_ref;
- r_iface_ref = 0;
+ visit_and_replace(memacc.left);
map<string, VariableDeclaration *> *members = 0;
if(StructDeclaration *strct = dynamic_cast<StructDeclaration *>(memacc.left->type))
void VariableResolver::visit(UnaryExpression &unary)
{
- TraversingVisitor::visit(unary);
- r_iface_ref = 0;
+ visit_and_replace(unary.expression);
}
void VariableResolver::visit(BinaryExpression &binary)
/* The subscript expression is not a part of the primary assignment
target. */
SetFlag set(record_target, false);
- binary.right->visit(*this);
+ visit_and_replace(binary.right);
}
- r_iface_ref = 0;
- binary.left->visit(*this);
- if(r_iface_ref)
- binary.left = r_iface_ref;
+ visit_and_replace(binary.left);
}
else
- TraversingVisitor::visit(binary);
-
- r_iface_ref = 0;
+ {
+ visit_and_replace(binary.left);
+ visit_and_replace(binary.right);
+ }
}
void VariableResolver::visit(Assignment &assign)
{
SetFlag set(record_target);
r_assignment_target = 0;
- assign.left->visit(*this);
+ visit_and_replace(assign.left);
r_any_resolved |= (r_assignment_target!=assign.target_declaration);
assign.target_declaration = r_assignment_target;
}
r_self_referencing = false;
- assign.right->visit(*this);
+ visit_and_replace(assign.right);
assign.self_referencing = (r_self_referencing || assign.oper->token[0]!='=');
-
- r_iface_ref = 0;
}
void VariableResolver::visit(FunctionCall &call)
{
- TraversingVisitor::visit(call);
- r_iface_ref = 0;
+ for(NodeArray<Expression>::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
+ visit_and_replace(*i);
}
void VariableResolver::visit(VariableDeclaration &var)
resolve(unary, basic, unary.expression->lvalue);
}
-void ExpressionResolver::visit(BinaryExpression &binary)
+void ExpressionResolver::visit(BinaryExpression &binary, bool assign)
{
- TraversingVisitor::visit(binary);
-
/* Binary operators are only defined for basic types (not for image or
structure types). */
BasicTypeDeclaration *basic_left = dynamic_cast<BasicTypeDeclaration *>(binary.left->type);
Compatibility elem_compat = get_compatibility(*elem_left, *elem_right);
if(elem_compat==NOT_COMPATIBLE)
return;
+ if(assign && (compat==LEFT_CONVERTIBLE || elem_compat==LEFT_CONVERTIBLE))
+ return;
TypeDeclaration *type = 0;
char oper2 = binary.oper->token[1];
}
else if((oper=='<' || oper=='>') && oper2==oper)
{
- // Shifts only apply to integers.
- if(basic_left->kind!=BasicTypeDeclaration::INT || basic_right->kind!=BasicTypeDeclaration::INT)
+ // Shifts apply to integer scalars and vectors, with some restrictions.
+ if(elem_left->kind!=BasicTypeDeclaration::INT || elem_right->kind!=BasicTypeDeclaration::INT)
+ return;
+ unsigned left_size = (basic_left->kind==BasicTypeDeclaration::INT ? 1 : basic_left->kind==BasicTypeDeclaration::VECTOR ? basic_left->size : 0);
+ unsigned right_size = (basic_right->kind==BasicTypeDeclaration::INT ? 1 : basic_right->kind==BasicTypeDeclaration::VECTOR ? basic_right->size : 0);
+ if(!left_size || (left_size==1 && right_size!=1) || (left_size>1 && right_size!=1 && right_size!=left_size))
return;
type = basic_left;
+ // Don't perform conversion even if the operands are of different sizes.
+ compat = SAME_TYPE;
}
else if(oper=='+' || oper=='-' || oper=='*' || oper=='/')
{
else
return;
+ if(assign && type!=basic_left)
+ return;
+
bool converted = true;
if(compat==LEFT_CONVERTIBLE)
convert_to(binary.left, *basic_right);
if(!converted)
type = 0;
- resolve(binary, type, false);
+ resolve(binary, type, assign);
+}
+
+void ExpressionResolver::visit(BinaryExpression &binary)
+{
+ TraversingVisitor::visit(binary);
+ visit(binary, false);
}
void ExpressionResolver::visit(Assignment &assign)
{
TraversingVisitor::visit(assign);
+
+ if(assign.oper->token[0]!='=')
+ return visit(assign, true);
+ else if(assign.left->type!=assign.right->type)
+ {
+ BasicTypeDeclaration *basic_left = dynamic_cast<BasicTypeDeclaration *>(assign.left->type);
+ BasicTypeDeclaration *basic_right = dynamic_cast<BasicTypeDeclaration *>(assign.right->type);
+ if(!basic_left || !basic_right)
+ return;
+
+ Compatibility compat = get_compatibility(*basic_left, *basic_right);
+ if(compat==RIGHT_CONVERTIBLE)
+ convert_to(assign.right, *basic_left);
+ else if(compat!=SAME_TYPE)
+ return;
+ }
+
resolve(assign, assign.left->type, true);
}