فهرست منبع

LibJS: Add support for hex, octal & binary big integer literals

Idan Horowitz 4 سال پیش
والد
کامیت
690eb3bb8a
3فایلهای تغییر یافته به همراه34 افزوده شده و 0 حذف شده
  1. 10 0
      Userland/Libraries/LibJS/AST.cpp
  2. 12 0
      Userland/Libraries/LibJS/Lexer.cpp
  3. 12 0
      Userland/Libraries/LibJS/Tests/builtins/BigInt/bigint-basic.js

+ 10 - 0
Userland/Libraries/LibJS/AST.cpp

@@ -1830,6 +1830,16 @@ Value NumericLiteral::execute(Interpreter& interpreter, GlobalObject&) const
 Value BigIntLiteral::execute(Interpreter& interpreter, GlobalObject&) const
 Value BigIntLiteral::execute(Interpreter& interpreter, GlobalObject&) const
 {
 {
     InterpreterNodeScope node_scope { interpreter, *this };
     InterpreterNodeScope node_scope { interpreter, *this };
+    Crypto::SignedBigInteger integer;
+    if (m_value[0] == '0' && m_value.length() >= 3) {
+        if (m_value[1] == 'x' || m_value[1] == 'X') {
+            return js_bigint(interpreter.heap(), Crypto::SignedBigInteger::from_base16(m_value.substring(2, m_value.length() - 3)));
+        } else if (m_value[1] == 'o' || m_value[1] == 'O') {
+            return js_bigint(interpreter.heap(), Crypto::SignedBigInteger::from_base8(m_value.substring(2, m_value.length() - 3)));
+        } else if (m_value[1] == 'b' || m_value[1] == 'B') {
+            return js_bigint(interpreter.heap(), Crypto::SignedBigInteger::from_base2(m_value.substring(2, m_value.length() - 3)));
+        }
+    }
     return js_bigint(interpreter.heap(), Crypto::SignedBigInteger::from_base10(m_value.substring(0, m_value.length() - 1)));
     return js_bigint(interpreter.heap(), Crypto::SignedBigInteger::from_base10(m_value.substring(0, m_value.length() - 1)));
 }
 }
 
 

+ 12 - 0
Userland/Libraries/LibJS/Lexer.cpp

@@ -466,12 +466,24 @@ Token Lexer::next()
             } else if (m_current_char == 'o' || m_current_char == 'O') {
             } else if (m_current_char == 'o' || m_current_char == 'O') {
                 // octal
                 // octal
                 is_invalid_numeric_literal = !consume_octal_number();
                 is_invalid_numeric_literal = !consume_octal_number();
+                if (m_current_char == 'n') {
+                    consume();
+                    token_type = TokenType::BigIntLiteral;
+                }
             } else if (m_current_char == 'b' || m_current_char == 'B') {
             } else if (m_current_char == 'b' || m_current_char == 'B') {
                 // binary
                 // binary
                 is_invalid_numeric_literal = !consume_binary_number();
                 is_invalid_numeric_literal = !consume_binary_number();
+                if (m_current_char == 'n') {
+                    consume();
+                    token_type = TokenType::BigIntLiteral;
+                }
             } else if (m_current_char == 'x' || m_current_char == 'X') {
             } else if (m_current_char == 'x' || m_current_char == 'X') {
                 // hexadecimal
                 // hexadecimal
                 is_invalid_numeric_literal = !consume_hexadecimal_number();
                 is_invalid_numeric_literal = !consume_hexadecimal_number();
+                if (m_current_char == 'n') {
+                    consume();
+                    token_type = TokenType::BigIntLiteral;
+                }
             } else if (m_current_char == 'n') {
             } else if (m_current_char == 'n') {
                 consume();
                 consume();
                 token_type = TokenType::BigIntLiteral;
                 token_type = TokenType::BigIntLiteral;

+ 12 - 0
Userland/Libraries/LibJS/Tests/builtins/BigInt/bigint-basic.js

@@ -7,6 +7,18 @@ describe("correct behavior", () => {
         expect("" + 123n).toBe("123");
         expect("" + 123n).toBe("123");
     });
     });
 
 
+    test("hex literals", () => {
+        expect(0xffn).toBe(255n);
+    });
+
+    test("octal literals", () => {
+        expect(0o10n).toBe(8n);
+    });
+
+    test("binary literals", () => {
+        expect(0b10n).toBe(2n);
+    });
+
     test("arithmetic operators", () => {
     test("arithmetic operators", () => {
         let bigint = 123n;
         let bigint = 123n;
         expect(-bigint).toBe(-123n);
         expect(-bigint).toBe(-123n);