Stuck on Runtime Errors: Binary Operators (2/2) #cq1

I’m stuck on Stage #cq1.

I’ve tried everything.

**Here are my logs: **
remote: [tester::#CQ1] Running tests for Stage #CQ1 (Evaluating Expressions - Runtime Errors: Binary Operators (2/2))
remote: [tester::#CQ1] [test-1] Running test case: 1
remote: [tester::#CQ1] [test-1] Writing contents to ./test.lox:
remote: [tester::#CQ1] [test-1] [test.lox] “bar” + true
remote: [tester::#CQ1] [test-1] $ ./your_program.sh evaluate test.lox
remote: [your_program] bartrue
remote: [tester::#CQ1] [test-1] expected exit code 70, got 0
remote: [tester::#CQ1] [test-1] Test failed



python script:

from typing import Union

from token_types import Token, TokenType
from runtime_error import RuntimeError
from decimal import Decimal
from my_parser import Expr
import sys

class Evaluator:
def evaluate(self, expr: Expr) -> Union[Decimal, str, None]:
    try:
        if isinstance(expr, Expr.Literal):
            return self.evaluate_literal(expr)
        elif isinstance(expr, Expr.Unary):
            return self.evaluate_unary(expr)
        elif isinstance(expr, Expr.Binary):
            return self.evaluate_binary(expr)
        elif isinstance(expr, Expr.Grouping):
            return self.evaluate(expr.expression)
        else:
            raise ValueError(f"Unexpected expression type: {type(expr)}")
    except RuntimeError as e:
        self.runtime_error(e)
        sys.exit(70)  # Ensure we exit with code 70 for runtime errors

def evaluate_literal(self, expr: Expr.Literal) -> Union[Decimal, str, None]:
    if expr.value is True:
        return "true"
    elif expr.value is False:
        return "false"
    elif expr.value is None:
        return "nil"
    elif isinstance(expr.value, (int, float)):
        return Decimal(expr.value)
    elif isinstance(expr.value, str):
        return expr.value
    else:
        raise ValueError(f"Unexpected literal value: {expr.value}")

def evaluate_unary(self, expr: Expr.Unary) -> Union[Decimal, str, None]:
    right = self.evaluate(expr.right)
    if expr.operator.type == TokenType.BANG:
        if right == "true":
            return "false"
        elif right == "false" or right == "nil":
            return "true"
        elif isinstance(right, (Decimal, int)):
            return "false"
        else:
            raise RuntimeError(expr.operator, "Invalid operand type for unary '!'")
    elif expr.operator.type == TokenType.MINUS:
        if not isinstance(right, (Decimal, int)):
            raise RuntimeError(expr.operator, "Operand must be a number.")
        return -Decimal(right)
    else:
        raise RuntimeError(expr.operator, f"Unknown unary operator: {expr.operator}")

def evaluate_binary(self, expr: Expr.Binary) -> Union[Decimal, str, None]:
    left = self.evaluate(expr.left)
    right = self.evaluate(expr.right)

    if expr.operator.type == TokenType.PLUS:
        if isinstance(left, str) and isinstance(right, str):
            return left + right
        elif isinstance(left, (Decimal, int)) and isinstance(right, (Decimal, int)):
            return Decimal(left) + Decimal(right)
        else:
            raise RuntimeError(expr.operator, "Operands must be two numbers or two strings.")
    
    elif expr.operator.type == TokenType.MINUS:
        if isinstance(left, (Decimal, int)) and isinstance(right, (Decimal, int)):
            return Decimal(left) - Decimal(right)
        else:
            raise RuntimeError(expr.operator, "Operands must be numbers.")
    
    elif expr.operator.type == TokenType.STAR:
        if isinstance(left, (Decimal, int)) and isinstance(right, (Decimal, int)):
            return Decimal(left) * Decimal(right)
        else:
            raise RuntimeError(expr.operator, "Operands must be numbers.")
    
    elif expr.operator.type == TokenType.SLASH:
        if isinstance(left, (Decimal, int)) and isinstance(right, (Decimal, int)):
            if right == 0:
                raise RuntimeError(expr.operator, "Division by zero is not allowed.")
            return Decimal(left) / Decimal(right)
        else:
            raise RuntimeError(expr.operator, "Operands must be numbers.")
    
    elif expr.operator.type in {
        TokenType.GREATER, TokenType.GREATER_EQUAL, TokenType.LESS, 
        TokenType.LESS_EQUAL, TokenType.EQUAL_EQUAL, TokenType.BANG_EQUAL
    }:
        return self.evaluate_comparison(expr.operator, left, right)
    
    else:
        raise RuntimeError(expr.operator, f"Unexpected binary operator: {expr.operator}")

def evaluate_comparison(self, operator: Token, left: Union[Decimal, str], right: Union[Decimal, str]) -> str:
    if isinstance(left, (Decimal, int)) and isinstance(right, (Decimal, int)):
        if operator.type == TokenType.GREATER:
            return "true" if left > right else "false"
        elif operator.type == TokenType.GREATER_EQUAL:
            return "true" if left >= right else "false"
        elif operator.type == TokenType.LESS:
            return "true" if left < right else "false"
        elif operator.type == TokenType.LESS_EQUAL:
            return "true" if left <= right else "false"
        elif operator.type == TokenType.EQUAL_EQUAL:
            return "true" if left == right else "false"
        elif operator.type == TokenType.BANG_EQUAL:
            return "true" if left != right else "false"
    else:
        raise RuntimeError(operator, "Operands must be numbers.")

def runtime_error(self, error: RuntimeError) -> None:
    print(f"{error.args[1]}\n[line {error.operator.line}]", file=sys.stderr)

@dhruvi2209 I tried to run your code with codecrafters test --previous, but unfortunately it couldn’t pass the first stage anymore.

Could you try to make sure all previous stages are working, and put a copy of the updated code on GitHub? I can then take another look at it for you.

Yes of course. Here’s my GitHub repository: GitHub Repo

Kindly look into it.

@dhruvi2209 Thanks for sharing the GitHub link!

Unfortunately I still couldn’t get the code to pass the first stage.

Could you please install our CLI, and run:

codecrafters test --previous

And make sure the code are passing tests for all previous stages?

All the codes are present inside app folder and all the previous stages are working just fine. Parsing, Scanning stages are all done

All the codes are present inside app folder and all the previous stages are working just fine.

Sorry for asking (in the kindest way possible):

Have you tested the code after I responded that it’s not working anymore?


@dhruvi2209 Another way to test your code against earlier stages is to start a new repo, copy the code over from the old repo (except for .git), and try to pass tests in the new repo.

Feel free to notify me once the code passes all earlier stages. :handshake: