Add *= and /= operators for arithmetic types

This commit is contained in:
Tim Wojtulewicz 2025-07-03 15:56:53 -07:00
parent b034fd3f55
commit febe9b6177
10 changed files with 84 additions and 4 deletions

View file

@ -5,11 +5,12 @@
// Switching parser table type fixes ambiguity problems.
%define lr.type ielr
%expect 217
%expect 221
%token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY TOK_ASSERT
%token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF
%token TOK_BOOL TOK_BREAK TOK_CASE TOK_OPTION TOK_CONST
%token TOK_COMPOUND_MULTIPLY TOK_COMPOUND_DIVIDE
%token TOK_CONSTANT TOK_COPY TOK_COUNT TOK_DEFAULT TOK_DELETE
%token TOK_DOUBLE TOK_ELSE TOK_ENUM TOK_EVENT TOK_EXPORT TOK_FALLTHROUGH
%token TOK_FILE TOK_FOR TOK_FUNCTION TOK_GLOBAL TOK_HOOK TOK_ID TOK_IF TOK_INT
@ -37,7 +38,7 @@
%token TOK_NO_TEST
%left ','
%right '=' TOK_ADD_TO TOK_REMOVE_FROM TOK_ADD TOK_DELETE
%right '=' TOK_ADD_TO TOK_REMOVE_FROM TOK_ADD TOK_DELETE TOK_COMPOUND_MULTIPLY TOK_COMPOUND_DIVIDE
%right '?' ':'
%left TOK_OR_OR
%left TOK_AND_AND
@ -610,6 +611,32 @@ expr:
$$ = new TimesExpr({AdoptRef{}, $1}, {AdoptRef{}, $3});
}
| expr TOK_COMPOUND_MULTIPLY rhs
{
set_location(@1, @3);
ExprPtr lhs = {AdoptRef{}, $1};
ExprPtr rhs = {AdoptRef{}, $3};
auto tag1 = $1->GetType()->Tag();
if ( IsArithmetic($1->GetType()->Tag()) ) {
// Script optimization assumes that each AST
// node is distinct, hence the call to
// Duplicate() here.
ExprPtr result = make_intrusive<TimesExpr>(lhs->Duplicate(), rhs);
if ( result->GetType()->Tag() != tag1 )
result = make_intrusive<ArithCoerceExpr>(result, tag1);
$$ = new AssignExpr(lhs, result, false);
}
else {
$$->Error("Compound multiplication operator is only allowed for arithmetic types");
$$->SetError();
YYERROR;
}
}
| expr '/' expr
{
set_location(@1, @3);
@ -619,6 +646,32 @@ expr:
$$ = new DivideExpr({AdoptRef{}, $1}, {AdoptRef{}, $3});
}
| expr TOK_COMPOUND_DIVIDE rhs
{
set_location(@1, @3);
ExprPtr lhs = {AdoptRef{}, $1};
ExprPtr rhs = {AdoptRef{}, $3};
auto tag1 = $1->GetType()->Tag();
if ( IsArithmetic($1->GetType()->Tag()) ) {
// Script optimization assumes that each AST
// node is distinct, hence the call to
// Duplicate() here.
ExprPtr result = make_intrusive<DivideExpr>(lhs->Duplicate(), rhs);
if ( result->GetType()->Tag() != tag1 )
result = make_intrusive<ArithCoerceExpr>(result, tag1);
$$ = new AssignExpr(lhs, result, false);
}
else {
$$->Error("Compound division operator is only allowed for arithmetic types");
$$->SetError();
YYERROR;
}
}
| expr '%' expr
{
set_location(@1, @3);

View file

@ -304,6 +304,8 @@ ESCSEQ (\\([^\r\n]|[0-7]+|x[[:xdigit:]]+))
"+=" return TOK_ADD_TO;
"-=" return TOK_REMOVE_FROM;
"*=" return TOK_COMPOUND_MULTIPLY;
"/=" return TOK_COMPOUND_DIVIDE;
"==" return TOK_EQ;
"!=" return TOK_NE;

View file

@ -24,5 +24,7 @@ bitwise lshift (PASS)
bitwise rshift (PASS)
bitwise complement (PASS)
bitwise complement (PASS)
compound division operator (PASS)
compound multiplication operator (PASS)
max count value = 18446744073709551615 (PASS)
max count value = 18446744073709551615 (PASS)

View file

@ -26,6 +26,8 @@ relational operator (PASS)
relational operator (PASS)
relational operator (PASS)
division operator (PASS)
compound division operator (PASS)
compound multiplcation operator (PASS)
max double value = 1.7976931348623157e+308 (PASS)
4.9999999999999999e-13

View file

@ -19,3 +19,4 @@ error in <...>/init-mismatch.zeek, line 34: not a list of indices (s2)
error in <...>/init-mismatch.zeek, line 34: type clash in assignment (s3 = set(s2))
error in <...>/init-mismatch.zeek, line 36: pattern += op requires op to be a pattern (p += 3)
error in <...>/init-mismatch.zeek, line 38: illegal table constructor element (1.2.3.4)
error in <...>/init-mismatch.zeek, line 40: Compound multiplication operator is only allowed for arithmetic types (v)

View file

@ -20,3 +20,5 @@ assignment operator (PASS)
assignment operator (PASS)
bitwise lshift (PASS)
bitwise rshift (PASS)
compound division operator (FAIL)
compound multiplication operator (FAIL)

View file

@ -14,6 +14,7 @@ global c4: count = 255;
global c5: count = 18446744073709551615; # maximum allowed value
global c6: count = 0xffffffffffffffff; # maximum allowed value
global c7 = 1;
global c8: count = 10;
event zeek_init()
{
@ -52,6 +53,11 @@ event zeek_init()
test_case( "bitwise complement", ~c6 == 0 );
test_case( "bitwise complement", ~~c4 == c4 );
c8 /= 5;
test_case( "compound division operator", c8 == 2 );
c8 *= 3;
test_case( "compound multiplication operator", c8 == 6 );
# Max. value tests
local str1 = fmt("max count value = %d", c5);
@ -59,4 +65,3 @@ event zeek_init()
local str2 = fmt("max count value = %d", c6);
test_case( str2, str2 == "max count value = 18446744073709551615" );
}

View file

@ -29,6 +29,7 @@ global d19: double = 1.7976931348623157e308; # maximum allowed value
global d20 = 7.0;
global d21 = 7e0;
global d22 = 7e+1;
global d23 = 7.0;
event zeek_init()
{
@ -70,6 +71,11 @@ event zeek_init()
test_case( "relational operator", d17 > d3 );
test_case( "division operator", d3/2 == 1.5 );
d23 /= 3.5;
test_case( "compound division operator", d23 == 2.0 );
d23 *= 1.75;
test_case( "compound multiplcation operator", d23 == 3.5 );
# Max. value test
local str1 = fmt("max double value = %.16e", d19);
@ -111,4 +117,3 @@ event zeek_init()
print 0.1;
print 1.0;
}

View file

@ -37,4 +37,6 @@ p += 3;
t += { 1.2.3.4, F };
v *= vector();
print a, b;

View file

@ -18,6 +18,7 @@ global i8: int = 0xC;
global i9: int = -0xC;
global i10: int = -12;
global i11 = +3;
global i12: int = 10;
event zeek_init()
{
@ -52,4 +53,9 @@ event zeek_init()
test_case( "assignment operator", i2 == 5 );
test_case( "bitwise lshift", i6 << 1 == 24 );
test_case( "bitwise rshift", i6 >> 1 == 6 );
i11 /= 5;
test_case( "compound division operator", i11 == 2 );
i11 *= 3;
test_case( "compound multiplication operator", i11 == 6 );
}