Explorar o código

LibJS: Add basic support for modulo (%) in binary expressions

Andreas Kling %!s(int64=5) %!d(string=hai) anos
pai
achega
644ff1bbfd

+ 5 - 0
Libraries/LibJS/AST.cpp

@@ -244,6 +244,8 @@ Value BinaryExpression::execute(Interpreter& interpreter) const
         return mul(lhs_result, rhs_result);
     case BinaryOp::Slash:
         return div(lhs_result, rhs_result);
+    case BinaryOp::Modulo:
+        return mod(lhs_result, rhs_result);
     case BinaryOp::TypedEquals:
         return typed_eq(lhs_result, rhs_result);
     case BinaryOp::TypedInequals:
@@ -379,6 +381,9 @@ void BinaryExpression::dump(int indent) const
     case BinaryOp::Slash:
         op_string = "/";
         break;
+    case BinaryOp::Modulo:
+        op_string = "%";
+        break;
     case BinaryOp::TypedEquals:
         op_string = "===";
         break;

+ 1 - 0
Libraries/LibJS/AST.h

@@ -289,6 +289,7 @@ enum class BinaryOp {
     Minus,
     Asterisk,
     Slash,
+    Modulo,
     TypedEquals,
     TypedInequals,
     AbstractEquals,

+ 4 - 0
Libraries/LibJS/Parser.cpp

@@ -463,6 +463,9 @@ NonnullRefPtr<Expression> Parser::parse_secondary_expression(NonnullRefPtr<Expre
     case TokenType::SlashEquals:
         consume();
         return create_ast_node<AssignmentExpression>(AssignmentOp::DivisionAssignment, move(lhs), parse_expression(min_precedence, associativity));
+    case TokenType::Percent:
+        consume();
+        return create_ast_node<BinaryExpression>(BinaryOp::Modulo, 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));
@@ -871,6 +874,7 @@ bool Parser::match_secondary_expression() const
         || type == TokenType::AsteriskEquals
         || type == TokenType::Slash
         || type == TokenType::SlashEquals
+        || type == TokenType::Percent
         || type == TokenType::Equals
         || type == TokenType::EqualsEqualsEquals
         || type == TokenType::ExclamationMarkEqualsEquals

+ 6 - 0
Libraries/LibJS/Runtime/Value.cpp

@@ -239,6 +239,12 @@ Value div(Value lhs, Value rhs)
     return Value(lhs.to_number().as_double() / rhs.to_number().as_double());
 }
 
+Value mod(Value lhs, Value rhs)
+{
+    // FIXME: It seems like JavaScript should allow modulo for doubles as well(?)
+    return Value(lhs.to_i32() % rhs.to_i32());
+}
+
 Value typed_eq(Value lhs, Value rhs)
 {
     if (rhs.type() != lhs.type())

+ 1 - 0
Libraries/LibJS/Runtime/Value.h

@@ -195,6 +195,7 @@ Value add(Value lhs, Value rhs);
 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 eq(Value lhs, Value rhs);
 Value typed_eq(Value lhs, Value rhs);
 Value instance_of(Value lhs, Value rhs);

+ 8 - 0
Libraries/LibJS/Tests/modulo-basic.js

@@ -0,0 +1,8 @@
+function assert(x) { if (!x) throw 1; }
+
+try {
+    assert(10 % 3 === 1);
+    console.log("PASS");
+} catch (e) {
+    console.log("FAIL: " + e);
+}