mirror of
https://github.com/zeek/zeek.git
synced 2025-10-09 10:08:20 +00:00
Merge remote-tracking branch 'origin/topic/jsiwek/remove-match'
* origin/topic/jsiwek/remove-match: Remove the match expression (addressed #753).
This commit is contained in:
parent
5b2b03c6f7
commit
c78a391635
13 changed files with 14 additions and 259 deletions
5
CHANGES
5
CHANGES
|
@ -1,4 +1,9 @@
|
||||||
|
|
||||||
|
2.0-145 | 2012-03-09 15:10:35 -0800
|
||||||
|
|
||||||
|
* Remove the match expression. 'match' and 'using' are no longer
|
||||||
|
keywords. Addressed #753. (Jon Siwek)
|
||||||
|
|
||||||
2.0-143 | 2012-03-09 15:07:42 -0800
|
2.0-143 | 2012-03-09 15:07:42 -0800
|
||||||
|
|
||||||
* Fix a BRO_PROFILER_FILE/mkstemp portability issue. Addresses #794.
|
* Fix a BRO_PROFILER_FILE/mkstemp portability issue. Addresses #794.
|
||||||
|
|
4
NEWS
4
NEWS
|
@ -24,6 +24,10 @@ Bro 2.1
|
||||||
- The connection compressor was already deprecated in 2.0 and has now
|
- The connection compressor was already deprecated in 2.0 and has now
|
||||||
been removed from the code base.
|
been removed from the code base.
|
||||||
|
|
||||||
|
- We removed the "match" statement, which was no longer used by any of
|
||||||
|
the default scripts, nor was it likely to be used by anybody anytime
|
||||||
|
soon. With that, "match" and "using" are no longer reserved keywords.
|
||||||
|
|
||||||
TODO: Extend.
|
TODO: Extend.
|
||||||
|
|
||||||
Bro 2.0
|
Bro 2.0
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
2.0-143
|
2.0-145
|
||||||
|
|
145
src/Expr.cc
145
src/Expr.cc
|
@ -3633,151 +3633,6 @@ bool FieldAssignExpr::DoUnserialize(UnserialInfo* info)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordMatchExpr::RecordMatchExpr(Expr* op1 /* record to match */,
|
|
||||||
Expr* op2 /* cases to match against */)
|
|
||||||
: BinaryExpr(EXPR_MATCH, op1, op2)
|
|
||||||
{
|
|
||||||
BroType* result_type = 0;
|
|
||||||
|
|
||||||
// Make sure the second argument is of a suitable type.
|
|
||||||
if ( ! op2->Type()->IsSet() )
|
|
||||||
{
|
|
||||||
ExprError("matching must be done against a set of match records");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
type_list* elt_types = op2->Type()->AsSetType()->Indices()->Types();
|
|
||||||
|
|
||||||
if ( ! elt_types->length() ||
|
|
||||||
(*elt_types)[0]->Tag() != TYPE_RECORD )
|
|
||||||
{
|
|
||||||
ExprError("matching must be done against a set of match records");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RecordType* case_rec_type = (*elt_types)[0]->AsRecordType();
|
|
||||||
|
|
||||||
// NOTE: The "result" and "pred" field names are hardcoded here.
|
|
||||||
result_field_index = case_rec_type->FieldOffset("result");
|
|
||||||
|
|
||||||
if ( result_field_index < 0 )
|
|
||||||
{
|
|
||||||
ExprError("match records must have a $result field");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
result_type = case_rec_type->FieldType("result")->Ref();
|
|
||||||
|
|
||||||
// Check that pred exists, and that the first argument matches it.
|
|
||||||
if ( (pred_field_index = case_rec_type->FieldOffset("pred")) < 0 ||
|
|
||||||
case_rec_type->FieldType("pred")->Tag() != TYPE_FUNC )
|
|
||||||
{
|
|
||||||
ExprError("match records must have a $pred' field of function type");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FuncType* pred_type = case_rec_type->FieldType("pred")->AsFuncType();
|
|
||||||
type_list* pred_arg_types = pred_type->ArgTypes()->Types();
|
|
||||||
if ( pred_arg_types->length() != 1 ||
|
|
||||||
! check_and_promote_expr(op1, (*pred_arg_types)[0]) )
|
|
||||||
ExprError("record to match does not have the same type as predicate argument");
|
|
||||||
|
|
||||||
// NOTE: The "priority" field name is hardcoded here.
|
|
||||||
if ( (priority_field_index = case_rec_type->FieldOffset("priority")) >= 0 &&
|
|
||||||
! IsArithmetic(case_rec_type->FieldType("priority")->Tag()) )
|
|
||||||
ExprError("$priority field must have a numeric type");
|
|
||||||
|
|
||||||
SetType(result_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RecordMatchExpr::ExprDescribe(ODesc* d) const
|
|
||||||
{
|
|
||||||
if ( d->IsReadable() )
|
|
||||||
{
|
|
||||||
d->Add("match ");
|
|
||||||
op1->Describe(d);
|
|
||||||
d->Add(" using ");
|
|
||||||
op2->Describe(d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Val* RecordMatchExpr::Fold(Val* v1, Val* v2) const
|
|
||||||
{
|
|
||||||
TableVal* match_set = v2->AsTableVal();
|
|
||||||
if ( ! match_set )
|
|
||||||
Internal("non-table in RecordMatchExpr");
|
|
||||||
|
|
||||||
Val* return_val = 0;
|
|
||||||
double highest_priority = -1e100;
|
|
||||||
|
|
||||||
ListVal* match_recs = match_set->ConvertToList(TYPE_ANY);
|
|
||||||
for ( int i = 0; i < match_recs->Length(); ++i )
|
|
||||||
{
|
|
||||||
val_list args(1);
|
|
||||||
args.append(v1->Ref());
|
|
||||||
|
|
||||||
double this_priority = 0;
|
|
||||||
|
|
||||||
// ### Get rid of the double Index if TYPE_ANY->TYPE_RECORD.
|
|
||||||
Val* v = match_recs->Index(i)->AsListVal()->Index(0);
|
|
||||||
|
|
||||||
const RecordVal* match_rec = v->AsRecordVal();
|
|
||||||
if ( ! match_rec )
|
|
||||||
Internal("Element of match set is not a record");
|
|
||||||
|
|
||||||
if ( priority_field_index >= 0 )
|
|
||||||
{
|
|
||||||
this_priority =
|
|
||||||
match_rec->Lookup(priority_field_index)->CoerceToDouble();
|
|
||||||
if ( this_priority <= highest_priority )
|
|
||||||
{
|
|
||||||
Unref(v1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// No try/catch here; we pass exceptions upstream.
|
|
||||||
Val* pred_val =
|
|
||||||
match_rec->Lookup(pred_field_index)->AsFunc()->Call(&args);
|
|
||||||
bool is_zero = pred_val->IsZero();
|
|
||||||
Unref(pred_val);
|
|
||||||
|
|
||||||
if ( ! is_zero )
|
|
||||||
{
|
|
||||||
Val* new_return_val =
|
|
||||||
match_rec->Lookup(result_field_index);
|
|
||||||
|
|
||||||
Unref(return_val);
|
|
||||||
return_val = new_return_val->Ref();
|
|
||||||
|
|
||||||
if ( priority_field_index >= 0 )
|
|
||||||
highest_priority = this_priority;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Unref(match_recs);
|
|
||||||
|
|
||||||
return return_val;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_SERIAL(RecordMatchExpr, SER_RECORD_MATCH_EXPR);
|
|
||||||
|
|
||||||
bool RecordMatchExpr::DoSerialize(SerialInfo* info) const
|
|
||||||
{
|
|
||||||
DO_SERIALIZE(SER_RECORD_MATCH_EXPR, BinaryExpr);
|
|
||||||
return SERIALIZE(pred_field_index) && SERIALIZE(result_field_index) &&
|
|
||||||
SERIALIZE(priority_field_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RecordMatchExpr::DoUnserialize(UnserialInfo* info)
|
|
||||||
{
|
|
||||||
DO_UNSERIALIZE(BinaryExpr);
|
|
||||||
return UNSERIALIZE(&pred_field_index) && UNSERIALIZE(&result_field_index) &&
|
|
||||||
UNSERIALIZE(&priority_field_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
ArithCoerceExpr::ArithCoerceExpr(Expr* arg_op, TypeTag t)
|
ArithCoerceExpr::ArithCoerceExpr(Expr* arg_op, TypeTag t)
|
||||||
: UnaryExpr(EXPR_ARITH_COERCE, arg_op)
|
: UnaryExpr(EXPR_ARITH_COERCE, arg_op)
|
||||||
{
|
{
|
||||||
|
|
26
src/Expr.h
26
src/Expr.h
|
@ -823,32 +823,6 @@ protected:
|
||||||
string field_name;
|
string field_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RecordMatchExpr : public BinaryExpr {
|
|
||||||
public:
|
|
||||||
RecordMatchExpr(Expr* op1 /* record to match */,
|
|
||||||
Expr* op2 /* cases to match against */);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
friend class Expr;
|
|
||||||
RecordMatchExpr()
|
|
||||||
{
|
|
||||||
pred_field_index = result_field_index =
|
|
||||||
priority_field_index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual Val* Fold(Val* v1, Val* v2) const;
|
|
||||||
void ExprDescribe(ODesc*) const;
|
|
||||||
|
|
||||||
DECLARE_SERIAL(RecordMatchExpr);
|
|
||||||
|
|
||||||
// The following are used to hold the field offset of
|
|
||||||
// $pred, $result, $priority, so the names only need to
|
|
||||||
// be looked up at compile-time.
|
|
||||||
int pred_field_index;
|
|
||||||
int result_field_index;
|
|
||||||
int priority_field_index;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ArithCoerceExpr : public UnaryExpr {
|
class ArithCoerceExpr : public UnaryExpr {
|
||||||
public:
|
public:
|
||||||
ArithCoerceExpr(Expr* op, TypeTag t);
|
ArithCoerceExpr(Expr* op, TypeTag t);
|
||||||
|
|
|
@ -125,7 +125,7 @@ SERIAL_EXPR(FIELD_EXPR, 22)
|
||||||
SERIAL_EXPR(HAS_FIELD_EXPR, 23)
|
SERIAL_EXPR(HAS_FIELD_EXPR, 23)
|
||||||
SERIAL_EXPR(RECORD_CONSTRUCTOR_EXPR, 24)
|
SERIAL_EXPR(RECORD_CONSTRUCTOR_EXPR, 24)
|
||||||
SERIAL_EXPR(FIELD_ASSIGN_EXPR, 25)
|
SERIAL_EXPR(FIELD_ASSIGN_EXPR, 25)
|
||||||
SERIAL_EXPR(RECORD_MATCH_EXPR, 26)
|
// There used to be a SERIAL_EXPR(RECORD_MATCH_EXPR, 26) here
|
||||||
SERIAL_EXPR(ARITH_COERCE_EXPR, 27)
|
SERIAL_EXPR(ARITH_COERCE_EXPR, 27)
|
||||||
SERIAL_EXPR(RECORD_COERCE_EXPR, 28)
|
SERIAL_EXPR(RECORD_COERCE_EXPR, 28)
|
||||||
SERIAL_EXPR(FLATTEN_EXPR, 29)
|
SERIAL_EXPR(FLATTEN_EXPR, 29)
|
||||||
|
|
|
@ -125,7 +125,7 @@ protected:
|
||||||
|
|
||||||
// This will be increased whenever there is an incompatible change
|
// This will be increased whenever there is an incompatible change
|
||||||
// in the data format.
|
// in the data format.
|
||||||
static const uint32 DATA_FORMAT_VERSION = 21;
|
static const uint32 DATA_FORMAT_VERSION = 22;
|
||||||
|
|
||||||
ChunkedIO* io;
|
ChunkedIO* io;
|
||||||
|
|
||||||
|
|
10
src/parse.y
10
src/parse.y
|
@ -10,7 +10,7 @@
|
||||||
%token TOK_CONSTANT TOK_COPY TOK_COUNT TOK_COUNTER TOK_DEFAULT TOK_DELETE
|
%token TOK_CONSTANT TOK_COPY TOK_COUNT TOK_COUNTER TOK_DEFAULT TOK_DELETE
|
||||||
%token TOK_DOUBLE TOK_ELSE TOK_ENUM TOK_EVENT TOK_EXPORT TOK_FILE TOK_FOR
|
%token TOK_DOUBLE TOK_ELSE TOK_ENUM TOK_EVENT TOK_EXPORT TOK_FILE TOK_FOR
|
||||||
%token TOK_FUNCTION TOK_GLOBAL TOK_ID TOK_IF TOK_INT
|
%token TOK_FUNCTION TOK_GLOBAL TOK_ID TOK_IF TOK_INT
|
||||||
%token TOK_INTERVAL TOK_LIST TOK_LOCAL TOK_MODULE TOK_MATCH
|
%token TOK_INTERVAL TOK_LIST TOK_LOCAL TOK_MODULE
|
||||||
%token TOK_NEXT TOK_OF TOK_PATTERN TOK_PATTERN_TEXT
|
%token TOK_NEXT TOK_OF TOK_PATTERN TOK_PATTERN_TEXT
|
||||||
%token TOK_PORT TOK_PRINT TOK_RECORD TOK_REDEF
|
%token TOK_PORT TOK_PRINT TOK_RECORD TOK_REDEF
|
||||||
%token TOK_REMOVE_FROM TOK_RETURN TOK_SCHEDULE TOK_SET
|
%token TOK_REMOVE_FROM TOK_RETURN TOK_SCHEDULE TOK_SET
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
%left ',' '|'
|
%left ',' '|'
|
||||||
%right '=' TOK_ADD_TO TOK_REMOVE_FROM
|
%right '=' TOK_ADD_TO TOK_REMOVE_FROM
|
||||||
%right '?' ':' TOK_USING
|
%right '?' ':'
|
||||||
%left TOK_OR
|
%left TOK_OR
|
||||||
%left TOK_AND
|
%left TOK_AND
|
||||||
%nonassoc '<' '>' TOK_LE TOK_GE TOK_EQ TOK_NE
|
%nonassoc '<' '>' TOK_LE TOK_GE TOK_EQ TOK_NE
|
||||||
|
@ -504,12 +504,6 @@ expr:
|
||||||
$$ = new VectorConstructorExpr($3);
|
$$ = new VectorConstructorExpr($3);
|
||||||
}
|
}
|
||||||
|
|
||||||
| TOK_MATCH expr TOK_USING expr
|
|
||||||
{
|
|
||||||
set_location(@1, @4);
|
|
||||||
$$ = new RecordMatchExpr($2, $4);
|
|
||||||
}
|
|
||||||
|
|
||||||
| expr '(' opt_expr_list ')'
|
| expr '(' opt_expr_list ')'
|
||||||
{
|
{
|
||||||
set_location(@1, @4);
|
set_location(@1, @4);
|
||||||
|
|
|
@ -273,7 +273,6 @@ int return TOK_INT;
|
||||||
interval return TOK_INTERVAL;
|
interval return TOK_INTERVAL;
|
||||||
list return TOK_LIST;
|
list return TOK_LIST;
|
||||||
local return TOK_LOCAL;
|
local return TOK_LOCAL;
|
||||||
match return TOK_MATCH;
|
|
||||||
module return TOK_MODULE;
|
module return TOK_MODULE;
|
||||||
next return TOK_NEXT;
|
next return TOK_NEXT;
|
||||||
of return TOK_OF;
|
of return TOK_OF;
|
||||||
|
@ -295,7 +294,6 @@ timeout return TOK_TIMEOUT;
|
||||||
timer return TOK_TIMER;
|
timer return TOK_TIMER;
|
||||||
type return TOK_TYPE;
|
type return TOK_TYPE;
|
||||||
union return TOK_UNION;
|
union return TOK_UNION;
|
||||||
using return TOK_USING;
|
|
||||||
vector return TOK_VECTOR;
|
vector return TOK_VECTOR;
|
||||||
when return TOK_WHEN;
|
when return TOK_WHEN;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
default
|
|
||||||
it's big
|
|
||||||
it's really big
|
|
|
@ -1 +0,0 @@
|
||||||
2
|
|
|
@ -1,20 +0,0 @@
|
||||||
# @TEST-EXEC: bro %INPUT >output 2>&1
|
|
||||||
# @TEST-EXEC: btest-diff output
|
|
||||||
|
|
||||||
global match_stuff = {
|
|
||||||
[$pred(a: count) = { return a > 5; },
|
|
||||||
$result = "it's big",
|
|
||||||
$priority = 2],
|
|
||||||
|
|
||||||
[$pred(a: count) = { return a > 15; },
|
|
||||||
$result = "it's really big",
|
|
||||||
$priority = 3],
|
|
||||||
|
|
||||||
[$pred(a: count) = { return T; },
|
|
||||||
$result = "default",
|
|
||||||
$priority = 0],
|
|
||||||
};
|
|
||||||
|
|
||||||
print match 0 using match_stuff;
|
|
||||||
print match 10 using match_stuff;
|
|
||||||
print match 20 using match_stuff;
|
|
|
@ -1,51 +0,0 @@
|
||||||
# @TEST-EXEC: bro %INPUT >output 2>&1
|
|
||||||
# @TEST-EXEC: btest-diff output
|
|
||||||
|
|
||||||
type fakealert : record {
|
|
||||||
alert: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type match_rec : record {
|
|
||||||
result : count;
|
|
||||||
pred : function(rec : fakealert) : bool;
|
|
||||||
priority: count;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#global test_set : set[int] =
|
|
||||||
#{
|
|
||||||
#1, 2, 3
|
|
||||||
#};
|
|
||||||
|
|
||||||
global match_set : set[match_rec] =
|
|
||||||
{
|
|
||||||
[$result = 1, $pred(a: fakealert) = { return T; }, $priority = 8 ],
|
|
||||||
[$result = 2, $pred(a: fakealert) = { return T; }, $priority = 9 ]
|
|
||||||
};
|
|
||||||
|
|
||||||
global al : fakealert;
|
|
||||||
|
|
||||||
#global testset : set[fakealert] =
|
|
||||||
#{
|
|
||||||
# [$alert="hithere"]
|
|
||||||
#};
|
|
||||||
|
|
||||||
|
|
||||||
type nonalert: record {
|
|
||||||
alert : string;
|
|
||||||
pred : function(a : int) : int;
|
|
||||||
};
|
|
||||||
|
|
||||||
#global na : nonalert;
|
|
||||||
#na$alert = "5";
|
|
||||||
|
|
||||||
#al$alert = "hithere2";
|
|
||||||
#if (al in testset)
|
|
||||||
# print 1;
|
|
||||||
#else
|
|
||||||
# print 0;
|
|
||||||
|
|
||||||
|
|
||||||
al$alert = "hi";
|
|
||||||
print (match al using match_set);
|
|
Loading…
Add table
Add a link
Reference in a new issue