Implementing a VectorCoerceExpr.

Turns out we didn't have that yet.

I don't remember who implemented vectors originally, but he does owe
us all round at Jupiter ...
This commit is contained in:
Robin Sommer 2011-04-19 16:58:18 -07:00
parent b3b5a73113
commit 5a6311d360
7 changed files with 115 additions and 6 deletions

View file

@ -2497,12 +2497,7 @@ AssignExpr::AssignExpr(Expr* arg_op1, Expr* arg_op2, int arg_is_init,
bool AssignExpr::TypeCheck() bool AssignExpr::TypeCheck()
{ {
TypeTag bt1 = op1->Type()->Tag(); TypeTag bt1 = op1->Type()->Tag();
if ( IsVector(bt1) )
bt1 = op1->Type()->AsVectorType()->YieldType()->Tag();
TypeTag bt2 = op2->Type()->Tag(); TypeTag bt2 = op2->Type()->Tag();
if ( IsVector(bt2) )
bt2 = op2->Type()->AsVectorType()->YieldType()->Tag();
if ( bt1 == TYPE_LIST && bt2 == TYPE_ANY ) if ( bt1 == TYPE_LIST && bt2 == TYPE_ANY )
// This is ok because we cannot explicitly declare lists on // This is ok because we cannot explicitly declare lists on
@ -2531,6 +2526,13 @@ bool AssignExpr::TypeCheck()
return true; return true;
} }
if ( bt1 == TYPE_VECTOR && bt2 == bt1 &&
op2->Type()->AsVectorType()->IsUnspecifiedVector() )
{
op2 = new VectorCoerceExpr(op2, op1->Type()->AsVectorType());
return true;
}
if ( op1->Type()->Tag() == TYPE_RECORD && if ( op1->Type()->Tag() == TYPE_RECORD &&
op2->Type()->Tag() == TYPE_RECORD ) op2->Type()->Tag() == TYPE_RECORD )
{ {
@ -3506,6 +3508,13 @@ VectorConstructorExpr::VectorConstructorExpr(ListExpr* constructor_list)
if ( IsError() ) if ( IsError() )
return; return;
if ( constructor_list->Exprs().length() == 0 )
{
// vector().
SetType(new ::VectorType(base_type(TYPE_ANY)));
return;
}
BroType* t = merge_type_list(constructor_list); BroType* t = merge_type_list(constructor_list);
if ( t ) if ( t )
{ {
@ -4122,6 +4131,50 @@ bool TableCoerceExpr::DoUnserialize(UnserialInfo* info)
return true; return true;
} }
VectorCoerceExpr::VectorCoerceExpr(Expr* op, VectorType* v)
: UnaryExpr(EXPR_VECTOR_COERCE, op)
{
if ( IsError() )
return;
SetType(v->Ref());
if ( Type()->Tag() != TYPE_VECTOR )
ExprError("coercion to non-vector");
else if ( op->Type()->Tag() != TYPE_VECTOR )
ExprError("coercion of non-vector to vector");
}
VectorCoerceExpr::~VectorCoerceExpr()
{
}
Val* VectorCoerceExpr::Fold(Val* v) const
{
VectorVal* vv = v->AsVectorVal();
if ( vv->Size() > 0 )
Internal("coercion of non-empty vector");
return new VectorVal(Type()->Ref()->AsVectorType());
}
IMPLEMENT_SERIAL(VectorCoerceExpr, SER_VECTOR_COERCE_EXPR);
bool VectorCoerceExpr::DoSerialize(SerialInfo* info) const
{
DO_SERIALIZE(SER_VECTOR_COERCE_EXPR, UnaryExpr);
return true;
}
bool VectorCoerceExpr::DoUnserialize(UnserialInfo* info)
{
DO_UNSERIALIZE(UnaryExpr);
return true;
}
FlattenExpr::FlattenExpr(Expr* arg_op) FlattenExpr::FlattenExpr(Expr* arg_op)
: UnaryExpr(EXPR_FLATTEN, arg_op) : UnaryExpr(EXPR_FLATTEN, arg_op)
{ {
@ -5337,6 +5390,13 @@ int check_and_promote_expr(Expr*& e, BroType* t)
return 1; return 1;
} }
if ( t->Tag() == TYPE_VECTOR && et->Tag() == TYPE_VECTOR &&
et->AsVectorType()->IsUnspecifiedVector() )
{
e = new VectorCoerceExpr(e, t->AsVectorType());
return 1;
}
t->Error("type clash", e); t->Error("type clash", e);
return 0; return 0;
} }

View file

@ -40,7 +40,7 @@ typedef enum {
EXPR_CALL, EXPR_CALL,
EXPR_EVENT, EXPR_EVENT,
EXPR_SCHEDULE, EXPR_SCHEDULE,
EXPR_ARITH_COERCE, EXPR_RECORD_COERCE, EXPR_TABLE_COERCE, EXPR_ARITH_COERCE, EXPR_RECORD_COERCE, EXPR_TABLE_COERCE, EXPR_VECTOR_COERCE,
EXPR_SIZE, EXPR_SIZE,
EXPR_FLATTEN, EXPR_FLATTEN,
#define NUM_EXPRS (int(EXPR_FLATTEN) + 1) #define NUM_EXPRS (int(EXPR_FLATTEN) + 1)
@ -895,6 +895,20 @@ protected:
DECLARE_SERIAL(TableCoerceExpr); DECLARE_SERIAL(TableCoerceExpr);
}; };
class VectorCoerceExpr : public UnaryExpr {
public:
VectorCoerceExpr(Expr* op, VectorType* v);
~VectorCoerceExpr();
protected:
friend class Expr;
VectorCoerceExpr() { }
Val* Fold(Val* v) const;
DECLARE_SERIAL(VectorCoerceExpr);
};
// An internal operator for flattening array indices that are records // An internal operator for flattening array indices that are records
// into a list of individual values. // into a list of individual values.
class FlattenExpr : public UnaryExpr { class FlattenExpr : public UnaryExpr {

View file

@ -146,6 +146,7 @@ SERIAL_EXPR(TABLE_CONSTRUCTOR_EXPR, 40)
SERIAL_EXPR(SET_CONSTRUCTOR_EXPR, 41) SERIAL_EXPR(SET_CONSTRUCTOR_EXPR, 41)
SERIAL_EXPR(VECTOR_CONSTRUCTOR_EXPR, 42) SERIAL_EXPR(VECTOR_CONSTRUCTOR_EXPR, 42)
SERIAL_EXPR(TABLE_COERCE_EXPR, 43) SERIAL_EXPR(TABLE_COERCE_EXPR, 43)
SERIAL_EXPR(VECTOR_COERCE_EXPR, 44)
#define SERIAL_STMT(name, val) SERIAL_CONST(name, val, STMT) #define SERIAL_STMT(name, val) SERIAL_CONST(name, val, STMT)
SERIAL_STMT(STMT, 1) SERIAL_STMT(STMT, 1)

View file

@ -1290,6 +1290,11 @@ int VectorType::MatchesIndex(ListExpr*& index) const
MATCHES_INDEX_SCALAR : DOES_NOT_MATCH_INDEX; MATCHES_INDEX_SCALAR : DOES_NOT_MATCH_INDEX;
} }
bool VectorType::IsUnspecifiedVector() const
{
return yield_type->Tag() == TYPE_ANY;
}
IMPLEMENT_SERIAL(VectorType, SER_VECTOR_TYPE); IMPLEMENT_SERIAL(VectorType, SER_VECTOR_TYPE);
bool VectorType::DoSerialize(SerialInfo* info) const bool VectorType::DoSerialize(SerialInfo* info) const
@ -1651,6 +1656,7 @@ BroType* merge_types(const BroType* t1, const BroType* t2)
case TYPE_ADDR: case TYPE_ADDR:
case TYPE_NET: case TYPE_NET:
case TYPE_SUBNET: case TYPE_SUBNET:
case TYPE_BOOL:
case TYPE_ANY: case TYPE_ANY:
case TYPE_ERROR: case TYPE_ERROR:
return base_type(tg1); return base_type(tg1);

View file

@ -525,6 +525,10 @@ public:
int MatchesIndex(ListExpr*& index) const; int MatchesIndex(ListExpr*& index) const;
// Returns true if this table type is "unspecified", which is what one
// gets using an empty "vector()" constructor.
bool IsUnspecifiedVector() const;
protected: protected:
VectorType() { yield_type = 0; } VectorType() { yield_type = 0; }

View file

@ -0,0 +1,4 @@
[]
[1, 2, 3]
[T, F, T]
[]

View file

@ -0,0 +1,20 @@
# @TEST-EXEC: bro %INPUT >output 2>&1
# @TEST-EXEC: btest-diff output
type X: record {
a: vector of bool &default=vector(T, F, T);
b: vector of bool &default=vector();
};
global x: X;
global a: vector of count;
a = vector();
print a;
a = vector(1,2,3);
print a;
print x$a;
print x$b;