mirror of
https://github.com/zeek/zeek.git
synced 2025-10-09 18:18:19 +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
|
||||
|
||||
* 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
|
||||
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.
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
: UnaryExpr(EXPR_ARITH_COERCE, arg_op)
|
||||
{
|
||||
|
|
26
src/Expr.h
26
src/Expr.h
|
@ -823,32 +823,6 @@ protected:
|
|||
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 {
|
||||
public:
|
||||
ArithCoerceExpr(Expr* op, TypeTag t);
|
||||
|
|
|
@ -125,7 +125,7 @@ SERIAL_EXPR(FIELD_EXPR, 22)
|
|||
SERIAL_EXPR(HAS_FIELD_EXPR, 23)
|
||||
SERIAL_EXPR(RECORD_CONSTRUCTOR_EXPR, 24)
|
||||
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(RECORD_COERCE_EXPR, 28)
|
||||
SERIAL_EXPR(FLATTEN_EXPR, 29)
|
||||
|
|
|
@ -125,7 +125,7 @@ protected:
|
|||
|
||||
// This will be increased whenever there is an incompatible change
|
||||
// in the data format.
|
||||
static const uint32 DATA_FORMAT_VERSION = 21;
|
||||
static const uint32 DATA_FORMAT_VERSION = 22;
|
||||
|
||||
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_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_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_PORT TOK_PRINT TOK_RECORD TOK_REDEF
|
||||
%token TOK_REMOVE_FROM TOK_RETURN TOK_SCHEDULE TOK_SET
|
||||
|
@ -33,7 +33,7 @@
|
|||
|
||||
%left ',' '|'
|
||||
%right '=' TOK_ADD_TO TOK_REMOVE_FROM
|
||||
%right '?' ':' TOK_USING
|
||||
%right '?' ':'
|
||||
%left TOK_OR
|
||||
%left TOK_AND
|
||||
%nonassoc '<' '>' TOK_LE TOK_GE TOK_EQ TOK_NE
|
||||
|
@ -504,12 +504,6 @@ expr:
|
|||
$$ = new VectorConstructorExpr($3);
|
||||
}
|
||||
|
||||
| TOK_MATCH expr TOK_USING expr
|
||||
{
|
||||
set_location(@1, @4);
|
||||
$$ = new RecordMatchExpr($2, $4);
|
||||
}
|
||||
|
||||
| expr '(' opt_expr_list ')'
|
||||
{
|
||||
set_location(@1, @4);
|
||||
|
|
|
@ -273,7 +273,6 @@ int return TOK_INT;
|
|||
interval return TOK_INTERVAL;
|
||||
list return TOK_LIST;
|
||||
local return TOK_LOCAL;
|
||||
match return TOK_MATCH;
|
||||
module return TOK_MODULE;
|
||||
next return TOK_NEXT;
|
||||
of return TOK_OF;
|
||||
|
@ -295,7 +294,6 @@ timeout return TOK_TIMEOUT;
|
|||
timer return TOK_TIMER;
|
||||
type return TOK_TYPE;
|
||||
union return TOK_UNION;
|
||||
using return TOK_USING;
|
||||
vector return TOK_VECTOR;
|
||||
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