<commit_before>package pp.block5.cc.simple;

import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.antlr.v4.runtime.tree.TerminalNode;
import pp.block5.cc.ParseException;
import pp.block5.cc.pascal.SimplePascalBaseListener;
import pp.block5.cc.pascal.SimplePascalParser.*;

import java.util.ArrayList;
import java.util.List;

/** Class to type check and calculate flow entries and variable offsets. */
public class Checker extends SimplePascalBaseListener {
    /** Result of the latest call of {@link #check}. */
    private Result result;
    /** Variable scope for the latest call of {@link #check}. */
    private Scope scope;
    /** List of errors collected in the latest call of {@link #check}. */
    private List<String> errors;

    /** Runs this checker on a given parse tree,
     * and returns the checker result.
     * @throws ParseException if an error was found during checking.
     */
    public Result check(ParseTree tree) throws ParseException {
        this.scope = new Scope();
        this.result = new Result();
        this.errors = new ArrayList<>();
        new ParseTreeWalker().walk(this, tree);
        if (hasErrors()) {
            throw new ParseException(getErrors());
        }
        return this.result;
    }

    @Override
    public void exitAssStat(AssStatContext ctx) {
        setEntry(ctx, getEntry(ctx.expr()));
    }

    @Override
    public void exitBlock(BlockContext ctx) {
        setEntry(ctx, getEntry(ctx.stat(0)));
    }

    @Override
    public void exitBlockStat(BlockStatContext ctx) {
        setEntry(ctx, getEntry(ctx.block()));
    }

    // Override the listener methods for the statement nodes
    @Override
    public void exitBoolExpr(BoolExprContext ctx) {
        checkType(ctx.expr(0), Type.BOOL);
        checkType(ctx.expr(1), Type.BOOL);
        setType(ctx, Type.BOOL);
        setEntry(ctx, getEntry(ctx.expr(0)));
    }

    @Override
    public void exitBoolType(BoolTypeContext ctx) {
        setType(ctx, Type.BOOL);
    }

    @Override
    public void exitCompExpr(CompExprContext ctx) {
        checkType(ctx.expr(0), Type.INT);
        checkType(ctx.expr(1), Type.INT);
        setType(ctx, Type.BOOL);
        setEntry(ctx, getEntry(ctx.expr(0)));
    }

    @Override
    public void exitFalseExpr(FalseExprContext ctx) {
        setType(ctx, Type.BOOL);
        setEntry(ctx, ctx);
    }

    @Override
    public void exitIdTarget(IdTargetContext ctx) {
        setOffset(ctx, scope.offset(ctx.getText()));
        setType(ctx, scope.type(ctx.getText()));
        setEntry(ctx, ctx);
    }

    @Override
    public void exitIfStat(IfStatContext ctx) {
        checkType(ctx.expr(), Type.BOOL);

        setEntry(ctx, getEntry(ctx.expr()));
    }

    @Override
    public void exitInStat(InStatContext ctx) {
        setEntry(ctx, getEntry(ctx.target()));
    }

    @Override
    public void exitIntType(IntTypeContext ctx) {
        setType(ctx, Type.INT);
    }

    @Override
    public void exitIdExpr(IdExprContext ctx) {
        String id = ctx.ID().getText();
        Type type = this.scope.type(id);
        if (type == null) {
            addError(ctx, "Variable '%s' not declared", id);
        } else {
            setType(ctx, type);
            setOffset(ctx, this.scope.offset(id));
            setEntry(ctx, ctx);
        }
    }

    @Override
    public void exitMultExpr(MultExprContext ctx) {
        checkType(ctx.expr(0), Type.INT);
        checkType(ctx.expr(1), Type.INT);
        setType(ctx, Type.INT);
        setEntry(ctx, getEntry(ctx.expr(0)));
    }

    @Override
    public void exitNumExpr(NumExprContext ctx) {
        setType(ctx, Type.INT);
        setEntry(ctx, ctx);
    }

    @Override
    public void exitOutStat(OutStatContext ctx) {
        setEntry(ctx, getEntry(ctx.expr()));
    }

    @Override
    public void exitParExpr(ParExprContext ctx) {
        setType(ctx, getType(ctx.expr()));
        setEntry(ctx, getEntry(ctx.expr()));
    }

    @Override
    public void exitPlusExpr(PlusExprContext ctx) {
        checkType(ctx.expr(0), Type.INT);
        checkType(ctx.expr(1), Type.INT);
        setType(ctx, Type.INT);
        setEntry(ctx, getEntry(ctx.expr(0)));
    }

    @Override
    public void exitPrfExpr(PrfExprContext ctx) {
        Type type;
        if (ctx.prfOp().MINUS() != null) {
            type = Type.INT;
        } else {
            assert ctx.prfOp().NOT() != null;
            type = Type.BOOL;
        }
        checkType(ctx.expr(), type);
        setType(ctx, type);
        setEntry(ctx, getEntry(ctx.expr()));
    }

    @Override
    public void exitTrueExpr(TrueExprContext ctx) {
        setType(ctx, Type.BOOL);
        setEntry(ctx, ctx);
    }

    @Override
    public void exitVar(VarContext ctx) {
        Type type = getType(ctx.type());

        for (TerminalNode id : ctx.ID()) {
            if (!this.scope.put(id.getSymbol().getText(), type)) {
                addError(ctx, "Already declared '%s'", type);
            }
        }
        setEntry(ctx, ctx);
    }

    @Override
    public void exitWhileStat(WhileStatContext ctx) {<commit_msg>Copied exitIdExpr's body into exitIdTarget's body<commit_after>package pp.block5.cc.simple;

import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.antlr.v4.runtime.tree.TerminalNode;
import pp.block5.cc.ParseException;
import pp.block5.cc.pascal.SimplePascalBaseListener;
import pp.block5.cc.pascal.SimplePascalParser.*;

import java.util.ArrayList;
import java.util.List;

/** Class to type check and calculate flow entries and variable offsets. */
public class Checker extends SimplePascalBaseListener {
    /** Result of the latest call of {@link #check}. */
    private Result result;
    /** Variable scope for the latest call of {@link #check}. */
    private Scope scope;
    /** List of errors collected in the latest call of {@link #check}. */
    private List<String> errors;

    /** Runs this checker on a given parse tree,
     * and returns the checker result.
     * @throws ParseException if an error was found during checking.
     */
    public Result check(ParseTree tree) throws ParseException {
        this.scope = new Scope();
        this.result = new Result();
        this.errors = new ArrayList<>();
        new ParseTreeWalker().walk(this, tree);
        if (hasErrors()) {
            throw new ParseException(getErrors());
        }
        return this.result;
    }

    @Override
    public void exitAssStat(AssStatContext ctx) {
        setEntry(ctx, getEntry(ctx.expr()));
    }

    @Override
    public void exitBlock(BlockContext ctx) {
        setEntry(ctx, getEntry(ctx.stat(0)));
    }

    @Override
    public void exitBlockStat(BlockStatContext ctx) {
        setEntry(ctx, getEntry(ctx.block()));
    }

    // Override the listener methods for the statement nodes
    @Override
    public void exitBoolExpr(BoolExprContext ctx) {
        checkType(ctx.expr(0), Type.BOOL);
        checkType(ctx.expr(1), Type.BOOL);
        setType(ctx, Type.BOOL);
        setEntry(ctx, getEntry(ctx.expr(0)));
    }

    @Override
    public void exitBoolType(BoolTypeContext ctx) {
        setType(ctx, Type.BOOL);
    }

    @Override
    public void exitCompExpr(CompExprContext ctx) {
        checkType(ctx.expr(0), Type.INT);
        checkType(ctx.expr(1), Type.INT);
        setType(ctx, Type.BOOL);
        setEntry(ctx, getEntry(ctx.expr(0)));
    }

    @Override
    public void exitFalseExpr(FalseExprContext ctx) {
        setType(ctx, Type.BOOL);
        setEntry(ctx, ctx);
    }

    @Override
    public void exitIdTarget(IdTargetContext ctx) {
        String id = ctx.ID().getText();
        Type type = this.scope.type(id);
        if (type == null) {
            addError(ctx, "Variable '%s' not declared", id);
        } else {
            setType(ctx, type);
            setOffset(ctx, this.scope.offset(id));
            setEntry(ctx, ctx);
        }
    }

    @Override
    public void exitIfStat(IfStatContext ctx) {
        checkType(ctx.expr(), Type.BOOL);

        setEntry(ctx, getEntry(ctx.expr()));
    }

    @Override
    public void exitInStat(InStatContext ctx) {
        setEntry(ctx, getEntry(ctx.target()));
    }

    @Override
    public void exitIntType(IntTypeContext ctx) {
        setType(ctx, Type.INT);
    }

    @Override
    public void exitIdExpr(IdExprContext ctx) {
        String id = ctx.ID().getText();
        Type type = this.scope.type(id);
        if (type == null) {
            addError(ctx, "Variable '%s' not declared", id);
        } else {
            setType(ctx, type);
            setOffset(ctx, this.scope.offset(id));
            setEntry(ctx, ctx);
        }
    }

    @Override
    public void exitMultExpr(MultExprContext ctx) {
        checkType(ctx.expr(0), Type.INT);
        checkType(ctx.expr(1), Type.INT);
        setType(ctx, Type.INT);
        setEntry(ctx, getEntry(ctx.expr(0)));
    }

    @Override
    public void exitNumExpr(NumExprContext ctx) {
        setType(ctx, Type.INT);
        setEntry(ctx, ctx);
    }

    @Override
    public void exitOutStat(OutStatContext ctx) {
        setEntry(ctx, getEntry(ctx.expr()));
    }

    @Override
    public void exitParExpr(ParExprContext ctx) {
        setType(ctx, getType(ctx.expr()));
        setEntry(ctx, getEntry(ctx.expr()));
    }

    @Override
    public void exitPlusExpr(PlusExprContext ctx) {
        checkType(ctx.expr(0), Type.INT);
        checkType(ctx.expr(1), Type.INT);
        setType(ctx, Type.INT);
        setEntry(ctx, getEntry(ctx.expr(0)));
    }

    @Override
    public void exitPrfExpr(PrfExprContext ctx) {
        Type type;
        if (ctx.prfOp().MINUS() != null) {
            type = Type.INT;
        } else {
            assert ctx.prfOp().NOT() != null;
            type = Type.BOOL;
        }
        checkType(ctx.expr(), type);
        setType(ctx, type);
        setEntry(ctx, getEntry(ctx.expr()));
    }

    @Override
    public void exitTrueExpr(TrueExprContext ctx) {
        setType(ctx, Type.BOOL);
        setEntry(ctx, ctx);
    }

    @Override
    public void exitVar(VarContext ctx) {
        Type type = getType(ctx.type());

        for (TerminalNode id : ctx.ID()) {
            if (!this.scope.put(id.getText(), type)) {
                addError(ctx, "Already declared '%s'", type);
            }
        }
        setEntry(ctx, ctx);
    }

    @Override
    public void exitWhileStat(WhileStatContext ctx) {
{'fraction_non_alphanumeric': 0.12532612746925084, 'fraction_numerical': 0.004099888184867686, 'mean_word_length': 2.4400641025641026, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2259107', 'n_tokens_mistral': 3286, 'n_tokens_neox': 3219, 'n_words': 751}