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. // Switching parser table type fixes ambiguity problems.
%define lr.type ielr %define lr.type ielr
%expect 217 %expect 221
%token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY TOK_ASSERT %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_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF
%token TOK_BOOL TOK_BREAK TOK_CASE TOK_OPTION TOK_CONST %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_CONSTANT TOK_COPY TOK_COUNT TOK_DEFAULT TOK_DELETE
%token TOK_DOUBLE TOK_ELSE TOK_ENUM TOK_EVENT TOK_EXPORT TOK_FALLTHROUGH %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 %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 %token TOK_NO_TEST
%left ',' %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 '?' ':' %right '?' ':'
%left TOK_OR_OR %left TOK_OR_OR
%left TOK_AND_AND %left TOK_AND_AND
@ -610,6 +611,32 @@ expr:
$$ = new TimesExpr({AdoptRef{}, $1}, {AdoptRef{}, $3}); $$ = 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 | expr '/' expr
{ {
set_location(@1, @3); set_location(@1, @3);
@ -619,6 +646,32 @@ expr:
$$ = new DivideExpr({AdoptRef{}, $1}, {AdoptRef{}, $3}); $$ = 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 | expr '%' expr
{ {
set_location(@1, @3); set_location(@1, @3);

View file

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

View file

@ -24,5 +24,7 @@ bitwise lshift (PASS)
bitwise rshift (PASS) bitwise rshift (PASS)
bitwise complement (PASS) bitwise complement (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)
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)
relational operator (PASS) relational operator (PASS)
division operator (PASS) division operator (PASS)
compound division operator (PASS)
compound multiplcation operator (PASS)
max double value = 1.7976931348623157e+308 (PASS) max double value = 1.7976931348623157e+308 (PASS)
4.9999999999999999e-13 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 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 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 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) assignment operator (PASS)
bitwise lshift (PASS) bitwise lshift (PASS)
bitwise rshift (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 c5: count = 18446744073709551615; # maximum allowed value
global c6: count = 0xffffffffffffffff; # maximum allowed value global c6: count = 0xffffffffffffffff; # maximum allowed value
global c7 = 1; global c7 = 1;
global c8: count = 10;
event zeek_init() event zeek_init()
{ {
@ -52,6 +53,11 @@ event zeek_init()
test_case( "bitwise complement", ~c6 == 0 ); test_case( "bitwise complement", ~c6 == 0 );
test_case( "bitwise complement", ~~c4 == c4 ); 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 # Max. value tests
local str1 = fmt("max count value = %d", c5); local str1 = fmt("max count value = %d", c5);
@ -59,4 +65,3 @@ event zeek_init()
local str2 = fmt("max count value = %d", c6); local str2 = fmt("max count value = %d", c6);
test_case( str2, str2 == "max count value = 18446744073709551615" ); 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 d20 = 7.0;
global d21 = 7e0; global d21 = 7e0;
global d22 = 7e+1; global d22 = 7e+1;
global d23 = 7.0;
event zeek_init() event zeek_init()
{ {
@ -70,6 +71,11 @@ event zeek_init()
test_case( "relational operator", d17 > d3 ); test_case( "relational operator", d17 > d3 );
test_case( "division operator", d3/2 == 1.5 ); 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 # Max. value test
local str1 = fmt("max double value = %.16e", d19); local str1 = fmt("max double value = %.16e", d19);
@ -111,4 +117,3 @@ event zeek_init()
print 0.1; print 0.1;
print 1.0; print 1.0;
} }

View file

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

View file

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