diff options
author | Linus Groh <mail@linusgroh.de> | 2020-04-05 13:40:00 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-04-05 15:32:06 +0200 |
commit | 0403845d3edce9caf6823e0579074f57e9a4b9b9 (patch) | |
tree | f545e5cc2f4be20bd90d696174090e333077512c /Libraries | |
parent | eafd3dbaf88461ba7fb99ce8c5c6e7a295bed9b4 (diff) | |
download | serenity-0403845d3edce9caf6823e0579074f57e9a4b9b9.zip |
LibJS: Implement exponentiation (** operator)
Diffstat (limited to 'Libraries')
-rw-r--r-- | Libraries/LibJS/AST.cpp | 5 | ||||
-rw-r--r-- | Libraries/LibJS/AST.h | 1 | ||||
-rw-r--r-- | Libraries/LibJS/Parser.cpp | 4 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/Value.cpp | 6 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/Value.h | 1 | ||||
-rw-r--r-- | Libraries/LibJS/Tests/exponentiation-basic.js | 30 | ||||
-rw-r--r-- | Libraries/LibJS/Tests/modulo-basic.js | 2 |
7 files changed, 48 insertions, 1 deletions
diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index 5a7f8cc152..8bd75e4a90 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -283,6 +283,8 @@ Value BinaryExpression::execute(Interpreter& interpreter) const return div(lhs_result, rhs_result); case BinaryOp::Modulo: return mod(lhs_result, rhs_result); + case BinaryOp::Exponentiation: + return exp(lhs_result, rhs_result); case BinaryOp::TypedEquals: return typed_eq(lhs_result, rhs_result); case BinaryOp::TypedInequals: @@ -421,6 +423,9 @@ void BinaryExpression::dump(int indent) const case BinaryOp::Modulo: op_string = "%"; break; + case BinaryOp::Exponentiation: + op_string = "**"; + break; case BinaryOp::TypedEquals: op_string = "==="; break; diff --git a/Libraries/LibJS/AST.h b/Libraries/LibJS/AST.h index af6b13bced..3c0d761127 100644 --- a/Libraries/LibJS/AST.h +++ b/Libraries/LibJS/AST.h @@ -314,6 +314,7 @@ enum class BinaryOp { Multiplication, Division, Modulo, + Exponentiation, TypedEquals, TypedInequals, AbstractEquals, diff --git a/Libraries/LibJS/Parser.cpp b/Libraries/LibJS/Parser.cpp index 780b953121..3a9bfb2900 100644 --- a/Libraries/LibJS/Parser.cpp +++ b/Libraries/LibJS/Parser.cpp @@ -470,6 +470,9 @@ NonnullRefPtr<Expression> Parser::parse_secondary_expression(NonnullRefPtr<Expre case TokenType::Percent: consume(); 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: consume(); 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::SlashEquals || type == TokenType::Percent + || type == TokenType::DoubleAsterisk || type == TokenType::Equals || type == TokenType::EqualsEqualsEquals || type == TokenType::ExclamationMarkEqualsEquals diff --git a/Libraries/LibJS/Runtime/Value.cpp b/Libraries/LibJS/Runtime/Value.cpp index 13687cb5b3..ea0594245f 100644 --- a/Libraries/LibJS/Runtime/Value.cpp +++ b/Libraries/LibJS/Runtime/Value.cpp @@ -35,6 +35,7 @@ #include <LibJS/Runtime/PrimitiveString.h> #include <LibJS/Runtime/StringObject.h> #include <LibJS/Runtime/Value.h> +#include <math.h> namespace JS { @@ -268,6 +269,11 @@ Value mod(Value lhs, Value rhs) 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) { if (rhs.type() != lhs.type()) diff --git a/Libraries/LibJS/Runtime/Value.h b/Libraries/LibJS/Runtime/Value.h index df0e742ab9..b6d30c80f1 100644 --- a/Libraries/LibJS/Runtime/Value.h +++ b/Libraries/LibJS/Runtime/Value.h @@ -196,6 +196,7 @@ Value sub(Value lhs, Value rhs); Value mul(Value lhs, Value rhs); Value div(Value lhs, Value rhs); Value mod(Value lhs, Value rhs); +Value exp(Value lhs, Value rhs); Value eq(Value lhs, Value rhs); Value typed_eq(Value lhs, Value rhs); Value instance_of(Value lhs, Value rhs); diff --git a/Libraries/LibJS/Tests/exponentiation-basic.js b/Libraries/LibJS/Tests/exponentiation-basic.js new file mode 100644 index 0000000000..995fd08117 --- /dev/null +++ b/Libraries/LibJS/Tests/exponentiation-basic.js @@ -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); +} diff --git a/Libraries/LibJS/Tests/modulo-basic.js b/Libraries/LibJS/Tests/modulo-basic.js index 4f35c2b3ea..e5b74d60e2 100644 --- a/Libraries/LibJS/Tests/modulo-basic.js +++ b/Libraries/LibJS/Tests/modulo-basic.js @@ -3,7 +3,7 @@ try { assert(10.5 % 2.5 === 0.5); 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 assert(12 % 5 === 2); assert(-1 % 2 === -1); |