mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 16:12:44 +00:00 
			
		
		
		
	LibJS: Implement exponentiation (** operator)
This commit is contained in:
		
							parent
							
								
									eafd3dbaf8
								
							
						
					
					
						commit
						0403845d3e
					
				
					 7 changed files with 48 additions and 1 deletions
				
			
		|  | @ -283,6 +283,8 @@ Value BinaryExpression::execute(Interpreter& interpreter) const | ||||||
|         return div(lhs_result, rhs_result); |         return div(lhs_result, rhs_result); | ||||||
|     case BinaryOp::Modulo: |     case BinaryOp::Modulo: | ||||||
|         return mod(lhs_result, rhs_result); |         return mod(lhs_result, rhs_result); | ||||||
|  |     case BinaryOp::Exponentiation: | ||||||
|  |         return exp(lhs_result, rhs_result); | ||||||
|     case BinaryOp::TypedEquals: |     case BinaryOp::TypedEquals: | ||||||
|         return typed_eq(lhs_result, rhs_result); |         return typed_eq(lhs_result, rhs_result); | ||||||
|     case BinaryOp::TypedInequals: |     case BinaryOp::TypedInequals: | ||||||
|  | @ -421,6 +423,9 @@ void BinaryExpression::dump(int indent) const | ||||||
|     case BinaryOp::Modulo: |     case BinaryOp::Modulo: | ||||||
|         op_string = "%"; |         op_string = "%"; | ||||||
|         break; |         break; | ||||||
|  |     case BinaryOp::Exponentiation: | ||||||
|  |         op_string = "**"; | ||||||
|  |         break; | ||||||
|     case BinaryOp::TypedEquals: |     case BinaryOp::TypedEquals: | ||||||
|         op_string = "==="; |         op_string = "==="; | ||||||
|         break; |         break; | ||||||
|  |  | ||||||
|  | @ -314,6 +314,7 @@ enum class BinaryOp { | ||||||
|     Multiplication, |     Multiplication, | ||||||
|     Division, |     Division, | ||||||
|     Modulo, |     Modulo, | ||||||
|  |     Exponentiation, | ||||||
|     TypedEquals, |     TypedEquals, | ||||||
|     TypedInequals, |     TypedInequals, | ||||||
|     AbstractEquals, |     AbstractEquals, | ||||||
|  |  | ||||||
|  | @ -470,6 +470,9 @@ NonnullRefPtr<Expression> Parser::parse_secondary_expression(NonnullRefPtr<Expre | ||||||
|     case TokenType::Percent: |     case TokenType::Percent: | ||||||
|         consume(); |         consume(); | ||||||
|         return create_ast_node<BinaryExpression>(BinaryOp::Modulo, move(lhs), parse_expression(min_precedence, associativity)); |         return create_ast_node<BinaryExpression>(BinaryOp::Modulo, move(lhs), parse_expression(min_precedence, associativity)); | ||||||
|  |    case TokenType::DoubleAsterisk: | ||||||
|  |         consume(); | ||||||
|  |         return create_ast_node<BinaryExpression>(BinaryOp::Exponentiation, move(lhs), parse_expression(min_precedence, associativity)); | ||||||
|     case TokenType::GreaterThan: |     case TokenType::GreaterThan: | ||||||
|         consume(); |         consume(); | ||||||
|         return create_ast_node<BinaryExpression>(BinaryOp::GreaterThan, move(lhs), parse_expression(min_precedence, associativity)); |         return create_ast_node<BinaryExpression>(BinaryOp::GreaterThan, move(lhs), parse_expression(min_precedence, associativity)); | ||||||
|  | @ -905,6 +908,7 @@ bool Parser::match_secondary_expression() const | ||||||
|         || type == TokenType::Slash |         || type == TokenType::Slash | ||||||
|         || type == TokenType::SlashEquals |         || type == TokenType::SlashEquals | ||||||
|         || type == TokenType::Percent |         || type == TokenType::Percent | ||||||
|  |         || type == TokenType::DoubleAsterisk | ||||||
|         || type == TokenType::Equals |         || type == TokenType::Equals | ||||||
|         || type == TokenType::EqualsEqualsEquals |         || type == TokenType::EqualsEqualsEquals | ||||||
|         || type == TokenType::ExclamationMarkEqualsEquals |         || type == TokenType::ExclamationMarkEqualsEquals | ||||||
|  |  | ||||||
|  | @ -35,6 +35,7 @@ | ||||||
| #include <LibJS/Runtime/PrimitiveString.h> | #include <LibJS/Runtime/PrimitiveString.h> | ||||||
| #include <LibJS/Runtime/StringObject.h> | #include <LibJS/Runtime/StringObject.h> | ||||||
| #include <LibJS/Runtime/Value.h> | #include <LibJS/Runtime/Value.h> | ||||||
|  | #include <math.h> | ||||||
| 
 | 
 | ||||||
| namespace JS { | namespace JS { | ||||||
| 
 | 
 | ||||||
|  | @ -268,6 +269,11 @@ Value mod(Value lhs, Value rhs) | ||||||
|     return Value(index - trunc * period); |     return Value(index - trunc * period); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | Value exp(Value lhs, Value rhs) | ||||||
|  | { | ||||||
|  |     return Value(pow(lhs.to_number().as_double(), rhs.to_number().as_double())); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| Value typed_eq(Value lhs, Value rhs) | Value typed_eq(Value lhs, Value rhs) | ||||||
| { | { | ||||||
|     if (rhs.type() != lhs.type()) |     if (rhs.type() != lhs.type()) | ||||||
|  |  | ||||||
|  | @ -196,6 +196,7 @@ Value sub(Value lhs, Value rhs); | ||||||
| Value mul(Value lhs, Value rhs); | Value mul(Value lhs, Value rhs); | ||||||
| Value div(Value lhs, Value rhs); | Value div(Value lhs, Value rhs); | ||||||
| Value mod(Value lhs, Value rhs); | Value mod(Value lhs, Value rhs); | ||||||
|  | Value exp(Value lhs, Value rhs); | ||||||
| Value eq(Value lhs, Value rhs); | Value eq(Value lhs, Value rhs); | ||||||
| Value typed_eq(Value lhs, Value rhs); | Value typed_eq(Value lhs, Value rhs); | ||||||
| Value instance_of(Value lhs, Value rhs); | Value instance_of(Value lhs, Value rhs); | ||||||
|  |  | ||||||
							
								
								
									
										30
									
								
								Libraries/LibJS/Tests/exponentiation-basic.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								Libraries/LibJS/Tests/exponentiation-basic.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | ||||||
|  | function assert(x) { if (!x) throw 1; } | ||||||
|  | 
 | ||||||
|  | try { | ||||||
|  |     assert(2 ** 0 === 1); | ||||||
|  |     assert(2 ** 1 === 2); | ||||||
|  |     assert(2 ** 2 === 4); | ||||||
|  |     assert(2 ** 3 === 8); | ||||||
|  |     assert(2 ** -3 === 0.125); | ||||||
|  |     assert(3 ** 2 === 9); | ||||||
|  |     assert(0 ** 0 === 1); | ||||||
|  |     assert(2 ** 3 ** 2 === 512); | ||||||
|  |     assert(2 ** (3 ** 2) === 512); | ||||||
|  |     assert((2 ** 3) ** 2 === 64); | ||||||
|  |     assert("2" ** "3" === 8); | ||||||
|  |     assert("" ** [] === 1); | ||||||
|  |     assert([] ** null === 1); | ||||||
|  |     assert(null ** null === 1); | ||||||
|  |     assert(undefined ** null === 1); | ||||||
|  |     assert(isNaN(NaN ** 2)); | ||||||
|  |     assert(isNaN(2 ** NaN)); | ||||||
|  |     assert(isNaN(undefined ** 2)); | ||||||
|  |     assert(isNaN(2 ** undefined)); | ||||||
|  |     assert(isNaN(null ** undefined)); | ||||||
|  |     assert(isNaN(2 ** "foo")); | ||||||
|  |     assert(isNaN("foo" ** 2)); | ||||||
|  | 
 | ||||||
|  |     console.log("PASS"); | ||||||
|  | } catch (e) { | ||||||
|  |     console.log("FAIL: " + e); | ||||||
|  | } | ||||||
|  | @ -3,7 +3,7 @@ try { | ||||||
|     assert(10.5 % 2.5 === 0.5); |     assert(10.5 % 2.5 === 0.5); | ||||||
|     assert(-0.99 % 0.99 === -0); |     assert(-0.99 % 0.99 === -0); | ||||||
| 
 | 
 | ||||||
|     // Examples form MDN:
 |     // Examples from MDN:
 | ||||||
|     // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators
 |     // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators
 | ||||||
|     assert(12 % 5 === 2); |     assert(12 % 5 === 2); | ||||||
|     assert(-1 % 2 === -1); |     assert(-1 % 2 === -1); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Linus Groh
						Linus Groh