boa/syntax/ast/
op.rs

1//! This module implements various structure for logic handling.
2
3use crate::gc::{empty_trace, Finalize, Trace};
4use std::fmt::{Display, Formatter, Result};
5
6#[cfg(feature = "deser")]
7use serde::{Deserialize, Serialize};
8
9/// Arithmetic operators take numerical values (either literals or variables)
10/// as their operands and return a single numerical value.
11///
12/// More information:
13///  - [MDN documentation][mdn]
14///
15/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Arithmetic
16#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
17#[derive(Clone, Copy, Debug, Finalize, PartialEq)]
18pub enum NumOp {
19    /// The addition operator produces the sum of numeric operands or string concatenation.
20    ///
21    /// Syntax: `x + y`
22    ///
23    /// More information:
24    ///  - [ECMAScript reference][spec].
25    ///  - [MDN documentation][mdn]
26    ///
27    /// [spec]: https://tc39.es/ecma262/#sec-addition-operator-plus
28    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Addition
29    Add,
30
31    /// The subtraction operator subtracts the two operands, producing their difference.
32    ///
33    /// Syntax: `x - y`
34    ///
35    /// More information:
36    ///  - [ECMAScript reference][spec].
37    ///  - [MDN documentation][mdn]
38    ///
39    /// [spec]: https://tc39.es/ecma262/#sec-subtraction-operator-minus
40    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Subtraction
41    Sub,
42
43    /// The division operator produces the quotient of its operands where the left operand
44    /// is the dividend and the right operand is the divisor.
45    ///
46    /// Syntax: `x / y`
47    ///
48    /// More information:
49    ///  - [ECMAScript reference][spec]
50    ///  - [MDN documentation][mdn]
51    ///
52    /// [spec]: https://tc39.es/ecma262/#prod-MultiplicativeOperator
53    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Division
54    Div,
55
56    /// The multiplication operator produces the product of the operands.
57    ///
58    /// Syntax: `x * y`
59    ///
60    /// More information:
61    ///  - [ECMAScript reference][spec]
62    ///  - [MDN documentation][mdn]
63    ///
64    /// [spec]: https://tc39.es/ecma262/#prod-MultiplicativeExpression
65    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Multiplication
66    Mul,
67
68    /// The exponentiation operator returns the result of raising the first operand to
69    /// the power of the second operand.
70    ///
71    /// Syntax: `x ** y`
72    ///
73    /// The exponentiation operator is right-associative. a ** b ** c is equal to a ** (b ** c).
74    ///
75    /// More information:
76    ///  - [ECMAScript reference][spec]
77    ///  - [MDN documentation][mdn]
78    ///
79    /// [spec]: https://tc39.es/ecma262/#sec-exp-operator
80    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Exponentiation
81    Exp,
82
83    /// The remainder operator returns the remainder left over when one operand is divided by a second operand.
84    ///
85    /// Syntax: `x % y`
86    ///
87    /// The remainder operator always takes the sign of the dividend.
88    ///
89    /// More information:
90    ///  - [ECMAScript reference][spec]
91    ///  - [MDN documentation][mdn]
92    ///
93    /// [spec]: https://tc39.es/ecma262/#prod-MultiplicativeOperator
94    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Remainder
95    Mod,
96}
97
98impl Display for NumOp {
99    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
100        write!(
101            f,
102            "{}",
103            match *self {
104                Self::Add => "+",
105                Self::Sub => "-",
106                Self::Div => "/",
107                Self::Mul => "*",
108                Self::Exp => "**",
109                Self::Mod => "%",
110            }
111        )
112    }
113}
114
115unsafe impl Trace for NumOp {
116    empty_trace!();
117}
118
119/// A unary operator is one that takes a single operand/argument and performs an operation.
120///
121/// A unary operation is an operation with only one operand. This operand comes either
122/// before or after the operator. Unary operators are more efficient than standard JavaScript
123/// function calls.
124///
125/// More information:
126///  - [ECMAScript reference][spec]
127///  - [MDN documentation][mdn]
128///
129/// [spec]: https://tc39.es/ecma262/#prod-UnaryExpression
130/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Unary
131#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
132#[derive(Clone, Copy, Debug, Finalize, PartialEq)]
133pub enum UnaryOp {
134    /// The increment operator increments (adds one to) its operand and returns a value.
135    ///
136    /// Syntax: `++x`
137    ///
138    /// This operator increments and returns the value after incrementing.
139    ///
140    /// More information:
141    ///  - [ECMAScript reference][spec]
142    ///  - [MDN documentation][mdn]
143    ///
144    /// [spec]: https://tc39.es/ecma262/#sec-postfix-increment-operator
145    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Increment
146    IncrementPost,
147
148    /// The increment operator increments (adds one to) its operand and returns a value.
149    ///
150    /// Syntax: `x++`
151    ///
152    /// This operator increments and returns the value before incrementing.
153    ///
154    /// More information:
155    ///  - [ECMAScript reference][spec]
156    ///  - [MDN documentation][mdn]
157    ///
158    /// [spec]: https://tc39.es/ecma262/#sec-prefix-increment-operator
159    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Increment
160    IncrementPre,
161
162    /// The decrement operator decrements (subtracts one from) its operand and returns a value.
163    ///
164    /// Syntax: `--x`
165    ///
166    /// This operator decrements and returns the value before decrementing.
167    ///
168    /// More information:
169    ///  - [ECMAScript reference][spec]
170    ///  - [MDN documentation][mdn]
171    ///
172    /// [spec]: https://tc39.es/ecma262/#sec-postfix-decrement-operator
173    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Decrement
174    DecrementPost,
175
176    /// The decrement operator decrements (subtracts one from) its operand and returns a value.
177    ///
178    /// Syntax: `x--`
179    ///
180    /// This operator decrements the operand and returns the value after decrementing.
181    ///
182    /// More information:
183    ///  - [ECMAScript reference][spec]
184    ///  - [MDN documentation][mdn]
185    ///
186    /// [spec]: https://tc39.es/ecma262/#sec-prefix-decrement-operator
187    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Decrement
188    DecrementPre,
189
190    /// The unary negation operator precedes its operand and negates it.
191    ///
192    /// Syntax: `-x`
193    ///
194    /// Converts non-numbers data types to numbers like unary plus,
195    /// however, it performs an additional operation, negation.
196    ///
197    /// More information:
198    ///  - [ECMAScript reference][spec]
199    ///  - [MDN documentation][mdn]
200    ///
201    /// [spec]: https://tc39.es/ecma262/#sec-unary-minus-operator
202    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Unary_negation
203    Minus,
204
205    /// The unary plus operator attempts to convert the operand into a number, if it isn't already.
206    ///
207    /// Syntax: `+x`
208    ///
209    /// Although unary negation (`-`) also can convert non-numbers, unary plus is the fastest and preferred
210    /// way of converting something into a number, because it does not perform any other operations on the number.
211    /// It can convert `string` representations of integers and floats, as well as the non-string values `true`, `false`, and `null`.
212    ///
213    /// More information:
214    ///  - [ECMAScript reference][spec]
215    ///  - [MDN documentation][mdn]
216    ///
217    /// [spec]: https://tc39.es/ecma262/#sec-unary-plus-operator
218    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Unary_plus
219    Plus,
220
221    /// Returns `false` if its single operand can be converted to `true`; otherwise, returns `true`.
222    ///
223    /// Syntax: `!x`
224    ///
225    /// Boolean values simply get inverted: `!true === false` and `!false === true`.
226    /// Non-boolean values get converted to boolean values first, then are negated.
227    /// This means that it is possible to use a couple of NOT operators in series to explicitly
228    /// force the conversion of any value to the corresponding boolean primitive.
229    ///
230    /// More information:
231    ///  - [ECMAScript reference][spec]
232    ///  - [MDN documentation][mdn]
233    ///
234    /// [spec]: https://tc39.es/ecma262/#sec-logical-not-operator
235    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Logical_NOT
236    Not,
237
238    /// Performs the NOT operator on each bit.
239    ///
240    /// Syntax: `~x`
241    ///
242    /// NOT `a` yields the inverted value (or one's complement) of `a`.
243    /// Bitwise NOTing any number x yields -(x + 1). For example, ~-5 yields 4.
244    ///
245    /// More information:
246    ///  - [ECMAScript reference][spec]
247    ///  - [MDN documentation][mdn]
248    ///
249    /// [spec]: https://tc39.es/ecma262/#sec-bitwise-not-operator
250    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_NOT
251    Tilde,
252
253    /// The `typeof` operator returns a string indicating the type of the unevaluated operand.
254    ///
255    /// Syntax: `typeof x` or `typeof(x)`
256    ///
257    /// The `typeof` is a JavaScript keyword that will return the type of a variable when you call it.
258    /// You can use this to validate function parameters or check if variables are defined.
259    /// There are other uses as well.
260    ///
261    /// More information:
262    ///  - [ECMAScript reference][spec]
263    ///  - [MDN documentation][mdn]
264    ///
265    /// [spec]: https://tc39.es/ecma262/#sec-typeof-operator
266    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof
267    TypeOf,
268
269    /// The JavaScript `delete` operator removes a property from an object.
270    ///
271    /// Syntax: `delete x`
272    ///
273    /// Unlike what common belief suggests, the delete operator has nothing to do with
274    /// directly freeing memory. Memory management is done indirectly via breaking references.
275    /// If no more references to the same property are held, it is eventually released automatically.
276    ///
277    /// The `delete` operator returns `true` for all cases except when the property is an
278    /// [own](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty)
279    /// [non-configurable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_delete)
280    /// property, in which case, `false` is returned in non-strict mode.
281    ///
282    /// More information:
283    ///  - [ECMAScript reference][spec]
284    ///  - [MDN documentation][mdn]
285    ///
286    /// [spec]: https://tc39.es/ecma262/#sec-delete-operator
287    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete
288    Delete,
289
290    /// The `void` operator evaluates the given `expression` and then returns `undefined`.
291    ///
292    /// Syntax: `void x`
293    ///
294    /// This operator allows evaluating expressions that produce a value into places where an
295    /// expression that evaluates to `undefined` is desired.
296    /// The `void` operator is often used merely to obtain the `undefined` primitive value, usually using `void(0)`
297    /// (which is equivalent to `void 0`). In these cases, the global variable undefined can be used.
298    ///
299    /// When using an [immediately-invoked function expression](https://developer.mozilla.org/en-US/docs/Glossary/IIFE),
300    /// `void` can be used to force the function keyword to be treated as an expression instead of a declaration.
301    ///
302    /// More information:
303    ///  - [ECMAScript reference][spec]
304    ///  - [MDN documentation][mdn]
305    ///
306    /// [spec]: https://tc39.es/ecma262/#sec-void-operator
307    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void
308    Void,
309}
310
311impl Display for UnaryOp {
312    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
313        write!(
314            f,
315            "{}",
316            match *self {
317                Self::IncrementPost | Self::IncrementPre => "++",
318                Self::DecrementPost | Self::DecrementPre => "--",
319                Self::Plus => "+",
320                Self::Minus => "-",
321                Self::Not => "!",
322                Self::Tilde => "~",
323                Self::Delete => "delete",
324                Self::TypeOf => "typeof",
325                Self::Void => "void",
326            }
327        )
328    }
329}
330
331unsafe impl Trace for UnaryOp {
332    empty_trace!();
333}
334
335/// A bitwise operator is an operator used to perform bitwise operations
336/// on bit patterns or binary numerals that involve the manipulation of individual bits.
337///
338/// More information:
339///  - [MDN documentation][mdn]
340///
341/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Bitwise
342#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
343#[derive(Clone, Copy, Debug, Finalize, PartialEq)]
344pub enum BitOp {
345    /// Performs the AND operation on each pair of bits. a AND b yields 1 only if both a and b are 1.
346    ///
347    /// Syntax: `x & y`
348    ///
349    /// More information:
350    ///  - [ECMAScript reference][spec]
351    ///  - [MDN documentation][mdn]
352    ///
353    /// [spec]: https://tc39.es/ecma262/#prod-BitwiseANDExpression
354    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_AND
355    And,
356
357    /// Performs the OR operation on each pair of bits. a OR b yields 1 if either a or b is 1.
358    ///
359    /// Syntax: `x | y`
360    ///
361    /// More information:
362    ///  - [ECMAScript reference][spec]
363    ///  - [MDN documentation][mdn]
364    ///
365    /// [spec]: https://tc39.es/ecma262/#prod-BitwiseORExpression
366    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_OR
367    Or,
368
369    /// Performs the XOR operation on each pair of bits. a XOR b yields 1 if a and b are different.
370    ///
371    /// Syntax: `x ^ y`
372    ///
373    /// More information:
374    ///  - [ECMAScript reference][spec]
375    ///  - [MDN documentation][mdn]
376    ///
377    /// [spec]: https://tc39.es/ecma262/#prod-BitwiseXORExpression
378    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_XOR
379    Xor,
380
381    /// This operator shifts the first operand the specified number of bits to the left.
382    ///
383    /// Syntax: `x << y`
384    ///
385    /// Excess bits shifted off to the left are discarded. Zero bits are shifted in from the right.
386    ///
387    /// More information:
388    ///  - [ECMAScript reference][spec]
389    ///  - [MDN documentation][mdn]
390    ///
391    /// [spec]: https://tc39.es/ecma262/#sec-left-shift-operator
392    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Left_shift
393    Shl,
394
395    /// This operator shifts the first operand the specified number of bits to the right.
396    ///
397    /// Syntax: `x >> y`
398    ///
399    /// Excess bits shifted off to the right are discarded. Copies of the leftmost bit
400    /// are shifted in from the left. Since the new leftmost bit has the same value as
401    /// the previous leftmost bit, the sign bit (the leftmost bit) does not change.
402    /// Hence the name "sign-propagating".
403    ///
404    /// More information:
405    ///  - [ECMAScript reference][spec]
406    ///  - [MDN documentation][mdn]
407    ///
408    /// [spec]: https://tc39.es/ecma262/#sec-signed-right-shift-operator
409    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Right_shift
410    Shr,
411
412    /// This operator shifts the first operand the specified number of bits to the right.
413    ///
414    /// Syntax: `x >>> y`
415    ///
416    /// Excess bits shifted off to the right are discarded. Zero bits are shifted in
417    /// from the left. The sign bit becomes 0, so the result is always non-negative.
418    /// Unlike the other bitwise operators, zero-fill right shift returns an unsigned 32-bit integer.
419    ///
420    /// More information:
421    ///  - [ECMAScript reference][spec]
422    ///  - [MDN documentation][mdn]
423    ///
424    /// [spec]: https://tc39.es/ecma262/#sec-unsigned-right-shift-operator
425    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Unsigned_right_shift
426    UShr,
427}
428
429impl Display for BitOp {
430    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
431        write!(
432            f,
433            "{}",
434            match *self {
435                Self::And => "&",
436                Self::Or => "|",
437                Self::Xor => "^",
438                Self::Shl => "<<",
439                Self::Shr => ">>",
440                Self::UShr => ">>>",
441            }
442        )
443    }
444}
445
446unsafe impl Trace for BitOp {
447    empty_trace!();
448}
449
450/// A comparison operator compares its operands and returns a logical value based on whether the comparison is true.
451///
452/// The operands can be numerical, string, logical, or object values. Strings are compared based on standard
453/// lexicographical ordering, using Unicode values. In most cases, if the two operands are not of the same type,
454/// JavaScript attempts to convert them to an appropriate type for the comparison. This behavior generally results in
455/// comparing the operands numerically. The sole exceptions to type conversion within comparisons involve the `===` and `!==`
456/// operators, which perform strict equality and inequality comparisons. These operators do not attempt to convert the operands
457/// to compatible types before checking equality.
458///
459/// More information:
460///  - [ECMAScript reference][spec]
461///  - [MDN documentation][mdn]
462///
463/// [spec]: tc39.es/ecma262/#sec-testing-and-comparison-operations
464/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Comparison
465#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
466#[derive(Clone, Copy, Debug, Finalize, PartialEq)]
467pub enum CompOp {
468    /// The equality operator converts the operands if they are not of the same type, then applies
469    /// strict comparison.
470    ///
471    /// Syntax: `y == y`
472    ///
473    /// If both operands are objects, then JavaScript compares internal references which are equal
474    /// when operands refer to the same object in memory.
475    ///
476    /// More information:
477    ///  - [ECMAScript reference][spec]
478    ///  - [MDN documentation][mdn]
479    ///
480    /// [spec]: https://tc39.es/ecma262/#sec-abstract-equality-comparison
481    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Equality
482    Equal,
483
484    /// The inequality operator returns `true` if the operands are not equal.
485    ///
486    /// Syntax: `x != y`
487    ///
488    /// If the two operands are not of the same type, JavaScript attempts to convert the operands
489    /// to an appropriate type for the comparison. If both operands are objects, then JavaScript
490    /// compares internal references which are not equal when operands refer to different objects
491    /// in memory.
492    ///
493    /// More information:
494    ///  - [ECMAScript reference][spec]
495    ///  - [MDN documentation][mdn]
496    ///
497    /// [spec]: https://tc39.es/ecma262/#prod-EqualityExpression
498    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Inequality
499    NotEqual,
500
501    /// The identity operator returns `true` if the operands are strictly equal **with no type
502    /// conversion**.
503    ///
504    /// Syntax: `x === y`
505    ///
506    /// Returns `true` if the operands are equal and of the same type.
507    ///
508    /// More information:
509    ///  - [ECMAScript reference][spec]
510    ///  - [MDN documentation][mdn]
511    ///
512    /// [spec]: https://tc39.es/ecma262/#sec-strict-equality-comparison
513    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Identity
514    StrictEqual,
515
516    /// The non-identity operator returns `true` if the operands **are not equal and/or not of the
517    /// same type**.
518    ///
519    /// Syntax: `x !== y`
520    ///
521    /// Returns `true` if the operands are of the same type but not equal, or are of different type.
522    ///
523    /// More information:
524    ///  - [ECMAScript reference][spec]
525    ///  - [MDN documentation][mdn]
526    ///
527    /// [spec]: https://tc39.es/ecma262/#prod-EqualityExpression
528    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Nonidentity>
529    StrictNotEqual,
530
531    /// The greater than operator returns `true` if the left operand is greater than the right
532    /// operand.
533    ///
534    /// Syntax: `x > y`
535    ///
536    /// Returns `true` if the left operand is greater than the right operand.
537    ///
538    /// More information:
539    ///  - [ECMAScript reference][spec]
540    ///  - [MDN documentation][mdn]
541    ///
542    /// [spec]: https://tc39.es/ecma262/#prod-RelationalExpression
543    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Greater_than_operator
544    GreaterThan,
545
546    /// The greater than or equal operator returns `true` if the left operand is greater than or
547    /// equal to the right operand.
548    ///
549    /// Syntax: `x >= y`
550    ///
551    /// Returns `true` if the left operand is greater than the right operand.
552    ///
553    /// More information:
554    ///  - [ECMAScript reference][spec]
555    ///  - [MDN documentation][mdn]
556    ///
557    /// [spec]: https://tc39.es/ecma262/#prod-RelationalExpression
558    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Greater_than_operator
559    GreaterThanOrEqual,
560
561    /// The less than operator returns `true` if the left operand is less than the right operand.
562    ///
563    /// Syntax: `x < y`
564    ///
565    /// Returns `true` if the left operand is less than the right operand.
566    ///
567    /// More information:
568    ///  - [ECMAScript reference][spec]
569    ///  - [MDN documentation][mdn]
570    ///
571    /// [spec]: https://tc39.es/ecma262/#prod-RelationalExpression
572    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Less_than_operator
573    LessThan,
574
575    /// The less than or equal operator returns `true` if the left operand is less than or equal to
576    /// the right operand.
577    ///
578    /// Syntax: `x <= y`
579    ///
580    /// Returns `true` if the left operand is less than or equal to the right operand.
581    ///
582    /// More information:
583    ///  - [ECMAScript reference][spec]
584    ///  - [MDN documentation][mdn]
585    ///
586    /// [spec]: https://tc39.es/ecma262/#prod-RelationalExpression
587    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Less_than_or_equal_operator
588    LessThanOrEqual,
589
590    /// The `in` operator returns `true` if the specified property is in the specified object or
591    /// its prototype chain.
592    ///
593    /// Syntax: `prop in object`
594    ///
595    /// Returns `true` the specified property is in the specified object or its prototype chain.
596    ///
597    /// More information:
598    ///  - [ECMAScript reference][spec]
599    ///  - [MDN documentation][mdn]
600    ///
601    /// [spec]: https://tc39.es/ecma262/#prod-RelationalExpression
602    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in
603    In,
604
605    /// The `instanceof` operator returns `true` if the specified object is an instance of the
606    /// right hand side object.
607    ///
608    /// Syntax: `obj instanceof Object`
609    ///
610    /// Returns `true` the `prototype` property of the right hand side constructor appears anywhere
611    /// in the prototype chain of the object.
612    ///
613    /// More information:
614    ///  - [ECMAScript reference][spec]
615    ///  - [MDN documentation][mdn]
616    ///
617    /// [spec]: https://tc39.es/ecma262/#prod-RelationalExpression
618    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof
619    InstanceOf,
620}
621
622impl Display for CompOp {
623    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
624        write!(
625            f,
626            "{}",
627            match *self {
628                Self::Equal => "==",
629                Self::NotEqual => "!=",
630                Self::StrictEqual => "===",
631                Self::StrictNotEqual => "!==",
632                Self::GreaterThan => ">",
633                Self::GreaterThanOrEqual => ">=",
634                Self::LessThan => "<",
635                Self::LessThanOrEqual => "<=",
636                Self::In => "in",
637                Self::InstanceOf => "instanceof",
638            }
639        )
640    }
641}
642
643unsafe impl Trace for CompOp {
644    empty_trace!();
645}
646
647/// Logical operators are typically used with Boolean (logical) values; when they are, they return a Boolean value.
648///
649/// However, the `&&` and `||` operators actually return the value of one of the specified operands,
650/// so if these operators are used with non-Boolean values, they may return a non-Boolean value.
651///
652/// More information:
653///  - [ECMAScript reference][spec]
654///  - [MDN documentation][mdn]
655///
656/// [spec]: https://tc39.es/ecma262/#sec-binary-logical-operators
657/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Logical
658#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
659#[derive(Clone, Copy, Debug, Finalize, PartialEq)]
660pub enum LogOp {
661    /// The logical AND operator returns the value of the first operand if it can be coerced into `false`;
662    /// otherwise, it returns the second operand.
663    ///
664    /// Syntax: `x && y`
665    ///
666    /// More information:
667    ///  - [ECMAScript reference][spec]
668    ///  - [MDN documentation][mdn]
669    ///
670    /// [spec]: https://tc39.es/ecma262/#prod-LogicalANDExpression
671    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Logical_AND
672    And,
673
674    /// The logical OR operator returns the value the first operand if it can be coerced into `true`;
675    /// otherwise, it returns the second operand.
676    ///
677    /// Syntax: `x || y`
678    ///
679    /// More information:
680    ///  - [ECMAScript reference][spec]
681    ///  - [MDN documentation][mdn]
682    ///
683    /// [spec]: https://tc39.es/ecma262/#prod-LogicalORExpression
684    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Logical_OR
685    Or,
686
687    /// The nullish coalescing operator is a logical operator that returns the second operand
688    /// when its first operand is null or undefined, and otherwise returns its first operand.
689    ///
690    /// Syntax: `x ?? y`
691    ///
692    /// More information:
693    ///  - [ECMAScript reference][spec]
694    ///  - [MDN documentation][mdn]
695    ///
696    /// [spec]: https://tc39.es/ecma262/#prod-CoalesceExpression
697    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator
698    Coalesce,
699}
700
701impl Display for LogOp {
702    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
703        write!(
704            f,
705            "{}",
706            match *self {
707                Self::And => "&&",
708                Self::Or => "||",
709                Self::Coalesce => "??",
710            }
711        )
712    }
713}
714
715unsafe impl Trace for LogOp {
716    empty_trace!();
717}
718
719/// This represents a binary operation between two values.
720#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
721#[derive(Clone, Copy, Debug, Finalize, PartialEq)]
722pub enum BinOp {
723    /// Numeric operation.
724    ///
725    /// see: [`NumOp`](enum.NumOp.html)
726    Num(NumOp),
727
728    /// Bitwise operation.
729    ///
730    /// see: [`BitOp`](enum.BitOp.html).
731    Bit(BitOp),
732
733    /// Comparitive operation.
734    ///
735    /// see: [`CompOp`](enum.CompOp.html).
736    Comp(CompOp),
737
738    /// Logical operation.
739    ///
740    /// see: [`LogOp`](enum.LogOp.html).
741    Log(LogOp),
742
743    /// Assign operation.
744    ///
745    /// see: [`AssignOp`](enum.AssignOp.html).
746    Assign(AssignOp),
747
748    /// Comma operation.
749    Comma,
750}
751
752impl From<NumOp> for BinOp {
753    fn from(op: NumOp) -> Self {
754        Self::Num(op)
755    }
756}
757
758impl From<BitOp> for BinOp {
759    fn from(op: BitOp) -> Self {
760        Self::Bit(op)
761    }
762}
763
764impl From<CompOp> for BinOp {
765    fn from(op: CompOp) -> Self {
766        Self::Comp(op)
767    }
768}
769
770impl From<LogOp> for BinOp {
771    fn from(op: LogOp) -> Self {
772        Self::Log(op)
773    }
774}
775
776impl From<AssignOp> for BinOp {
777    fn from(op: AssignOp) -> Self {
778        Self::Assign(op)
779    }
780}
781
782impl Display for BinOp {
783    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
784        write!(
785            f,
786            "{}",
787            match *self {
788                Self::Num(ref op) => op.to_string(),
789                Self::Bit(ref op) => op.to_string(),
790                Self::Comp(ref op) => op.to_string(),
791                Self::Log(ref op) => op.to_string(),
792                Self::Assign(ref op) => op.to_string(),
793                Self::Comma => ",".to_string(),
794            }
795        )
796    }
797}
798
799unsafe impl Trace for BinOp {
800    empty_trace!();
801}
802
803/// An assignment operator assigns a value to its left operand based on the value of its right operand.
804///
805/// The simple assignment operator is equal (`=`), which assigns the value of its right operand to its
806/// left operand. That is, `x = y` assigns the value of `y to x`.
807///
808/// There are also compound assignment operators that are shorthand for the operations
809///
810/// More information:
811///  - [ECMAScript reference][spec]
812///  - [MDN documentation][mdn]
813///
814/// [spec]: https://tc39.es/ecma262/#prod-AssignmentOperator
815/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Assignment
816#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
817#[derive(Clone, Copy, Debug, Finalize, PartialEq)]
818pub enum AssignOp {
819    /// The addition assignment operator adds the value of the right operand to a variable and assigns the result to the variable.
820    ///
821    /// Syntax: `x += y`
822    ///
823    /// The types of the two operands determine the behavior of the addition assignment operator. Addition or concatenation is possible.
824    ///
825    /// More information:
826    ///  - [ECMAScript reference][spec]
827    ///  - [MDN documentation][mdn]
828    ///
829    /// [spec]: https://tc39.es/ecma262/#prod-AssignmentOperator
830    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Addition_assignment
831    Add,
832
833    /// The subtraction assignment operator subtracts the value of the right operand from a variable and assigns the result to the variable.
834    ///
835    /// Syntax: `x -= y`
836    ///
837    /// More information:
838    ///  - [ECMAScript reference][spec]
839    ///  - [MDN documentation][mdn]
840    ///
841    /// [spec]: https://tc39.es/ecma262/#prod-AssignmentOperator
842    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Subtraction_assignment
843    Sub,
844
845    /// The multiplication assignment operator multiplies a variable by the value of the right operand and assigns the result to the variable.
846    ///
847    /// Syntax: `x *= y`
848    ///
849    /// More information:
850    ///  - [ECMAScript reference][spec]
851    ///  - [MDN documentation][mdn]
852    ///
853    /// [spec]: https://tc39.es/ecma262/#prod-AssignmentOperator
854    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Multiplication_assignment
855    Mul,
856
857    /// The division assignment operator divides a variable by the value of the right operand and assigns the result to the variable.
858    ///
859    /// Syntax: `x /= y`
860    ///
861    /// More information:
862    ///  - [ECMAScript reference][spec]
863    ///  - [MDN documentation][mdn]
864    ///
865    /// [spec]: https://tc39.es/ecma262/#prod-AssignmentOperator
866    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Division_assignment
867    Div,
868
869    /// The remainder assignment operator divides a variable by the value of the right operand and assigns the remainder to the variable.
870    ///
871    /// Syntax: `x %= y`
872    ///
873    /// More information:
874    ///  - [ECMAScript reference][spec]
875    ///  - [MDN documentation][mdn]
876    ///
877    /// [spec]: https://tc39.es/ecma262/#prod-AssignmentOperator
878    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Remainder_assignment
879    Mod,
880
881    /// The exponentiation assignment operator raises the value of a variable to the power of the right operand.
882    ///
883    /// Syntax: `x ** y`
884    ///
885    /// More information:
886    ///  - [ECMAScript reference][spec]
887    ///  - [MDN documentation][mdn]
888    ///
889    /// [spec]: https://tc39.es/ecma262/#prod-AssignmentOperator
890    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Exponentiation_assignment
891    Exp,
892
893    /// The bitwise AND assignment operator uses the binary representation of both operands, does a bitwise AND operation on
894    /// them and assigns the result to the variable.
895    ///
896    /// Syntax: `x &= y`
897    ///
898    /// More information:
899    ///  - [ECMAScript reference][spec]
900    ///  - [MDN documentation][mdn]
901    ///
902    /// [spec]: https://tc39.es/ecma262/#prod-AssignmentOperator
903    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Bitwise_AND_assignment
904    And,
905
906    /// The bitwise OR assignment operator uses the binary representation of both operands, does a bitwise OR operation on
907    /// them and assigns the result to the variable.
908    ///
909    /// Syntax: `x |= y`
910    ///
911    /// More information:
912    ///  - [ECMAScript reference][spec]
913    ///  - [MDN documentation][mdn]
914    ///
915    /// [spec]: https://tc39.es/ecma262/#prod-AssignmentOperator
916    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Bitwise_OR_assignment
917    Or,
918
919    /// The bitwise XOR assignment operator uses the binary representation of both operands, does a bitwise XOR operation on
920    /// them and assigns the result to the variable.
921    ///
922    /// Syntax: `x ^= y`
923    ///
924    /// More information:
925    ///  - [ECMAScript reference][spec]
926    ///  - [MDN documentation][mdn]
927    ///
928    /// [spec]: https://tc39.es/ecma262/#prod-AssignmentOperator
929    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Bitwise_XOR_assignment
930    Xor,
931
932    /// The left shift assignment operator moves the specified amount of bits to the left and assigns the result to the variable.
933    ///
934    /// Syntax: `x <<= y`
935    ///
936    /// More information:
937    ///  - [ECMAScript reference][spec]
938    ///  - [MDN documentation][mdn]
939    ///
940    /// [spec]: https://tc39.es/ecma262/#prod-AssignmentOperator
941    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Left_shift_assignment
942    Shl,
943
944    /// The right shift assignment operator moves the specified amount of bits to the right and assigns the result to the variable.
945    ///
946    /// Syntax: `x >>= y`
947    ///
948    /// More information:
949    ///  - [ECMAScript reference][spec]
950    ///  - [MDN documentation][mdn]
951    ///
952    /// [spec]: https://tc39.es/ecma262/#prod-AssignmentOperator
953    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Right_shift_assignment
954    Shr,
955
956    /// The unsigned right shift assignment operator moves the specified amount of bits to the right and assigns the result to the variable.
957    ///
958    /// Syntax: `x >>>= y`
959    ///
960    /// More information:
961    ///  - [ECMAScript reference][spec]
962    ///  - [MDN documentation][mdn]
963    ///
964    /// [spec]: https://tc39.es/ecma262/#prod-AssignmentOperator
965    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unsigned_right_shift_assignment
966    Ushr,
967
968    /// The logical and assignment operator only assigns if the target variable is truthy.
969    ///
970    /// Syntax: `x &&= y`
971    ///
972    /// More information:
973    ///  - [ECMAScript reference][spec]
974    ///  - [MDN documentation][mdn]
975    ///
976    /// [spec]: https://tc39.es/ecma262/#prod-AssignmentExpression
977    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_AND_assignment
978    BoolAnd,
979
980    /// The logical or assignment operator only assigns if the target variable is falsy.
981    ///
982    /// Syntax: `x ||= y`
983    ///
984    /// More information:
985    ///  - [ECMAScript reference][spec]
986    ///  - [MDN documentation][mdn]
987    ///
988    /// [spec]: https://tc39.es/ecma262/#prod-AssignmentExpression
989    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_OR_assignment
990    BoolOr,
991
992    /// The logical nullish assignment operator only assigns if the target variable is nullish (null or undefined).
993    ///
994    /// Syntax: `x ??= y`
995    ///
996    /// More information:
997    ///  - [ECMAScript reference][spec]
998    ///  - [MDN documentation][mdn]
999    ///
1000    /// [spec]: https://tc39.es/ecma262/#prod-AssignmentExpression
1001    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_nullish_assignment
1002    Coalesce,
1003}
1004
1005unsafe impl Trace for AssignOp {
1006    empty_trace!();
1007}
1008
1009impl Display for AssignOp {
1010    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
1011        write!(
1012            f,
1013            "{}",
1014            match *self {
1015                Self::Add => "+=",
1016                Self::Sub => "-=",
1017                Self::Mul => "*=",
1018                Self::Exp => "**=",
1019                Self::Div => "/=",
1020                Self::Mod => "%=",
1021                Self::And => "&=",
1022                Self::Or => "|=",
1023                Self::Xor => "^=",
1024                Self::Shl => "<<=",
1025                Self::Shr => ">>=",
1026                Self::Ushr => ">>>=",
1027                Self::BoolAnd => "&&=",
1028                Self::BoolOr => "||=",
1029                Self::Coalesce => "??=",
1030            }
1031        )
1032    }
1033}