<commit_before>#include <iostream>
#include <cassert>
#include "IR.h"
#include "TypeChecker.h"

using namespace Bish;

void TypeChecker::visit(ReturnStatement *node) {
    if (visited(node) || node->type() != UndefinedTy) return;
    visited_set.insert(node);
    node->value->accept(this);
    node->set_type(node->value->type());
    // Propagate type of this return statement to the parent function.
    Function *f = dynamic_cast<Function*>(node->parent()->parent());
    assert(f);
    if (f->type() != UndefinedTy) {
        assert(f->type() == node->value->type() && "Invalid return type for function.");
    }
    propagate_if_undef(f, node);
}

void TypeChecker::visit(Function *node) {
    if (visited(node) || node->type() != UndefinedTy) return;
    visited_set.insert(node);
    for (std::vector<Variable *>::const_iterator I = node->args.begin(),
             E = node->args.end(); I != E; ++I) {
        (*I)->accept(this);
    }
    if (node->body) node->body->accept(this);
}

void TypeChecker::visit(FunctionCall *node) {
    if (visited(node) || node->type() != UndefinedTy) return;
    visited_set.insert(node);
    node->function->accept(this);
    for (std::vector<IRNode *>::const_iterator I = node->args.begin(),
           E = node->args.end(); I != E; ++I) {
      (*I)->accept(this);
    }
    node->set_type(node->function->type());
}

void TypeChecker::visit(ExternCall *node) {
    if (visited(node) || node->type() != UndefinedTy) return;
    visited_set.insert(node);
    node->set_type(UndefinedTy);
}

void TypeChecker::visit(IORedirection *node) {
    if (node->type() != UndefinedTy) return;
    node->a->accept(this);
    node->b->accept(this);
    node->set_type(UndefinedTy);
}

void TypeChecker::visit(Assignment *node) {
    if (visited(node) || node->type() != UndefinedTy) return;
    visited_set.insert(node);
    node->variable->accept(this);
    node->value->accept(this);
    if (node->variable->type() != UndefinedTy && node->value->type() != UndefinedTy) {
        assert(node->variable->type() == node->value->type() &&
               "Invalid type in assignment.");
    } else {
        node->variable->set_type(node->value->type());<commit_msg>Add function argument type checks.<commit_after>#include <iostream>
#include <cassert>
#include "IR.h"
#include "TypeChecker.h"

using namespace Bish;

void TypeChecker::visit(ReturnStatement *node) {
    if (visited(node) || node->type() != UndefinedTy) return;
    visited_set.insert(node);
    node->value->accept(this);
    node->set_type(node->value->type());
    // Propagate type of this return statement to the parent function.
    Function *f = dynamic_cast<Function*>(node->parent()->parent());
    assert(f);
    if (f->type() != UndefinedTy) {
        assert(f->type() == node->value->type() && "Invalid return type for function.");
    }
    propagate_if_undef(f, node);
}

void TypeChecker::visit(Function *node) {
    if (visited(node) || node->type() != UndefinedTy) return;
    visited_set.insert(node);
    for (std::vector<Variable *>::const_iterator I = node->args.begin(),
             E = node->args.end(); I != E; ++I) {
        (*I)->accept(this);
    }
    if (node->body) node->body->accept(this);
}

void TypeChecker::visit(FunctionCall *node) {
    if (visited(node) || node->type() != UndefinedTy) return;
    visited_set.insert(node);
    node->function->accept(this);
    unsigned i = 0;
    assert(node->function->body != NULL && "Calling an undefined function.");
    for (std::vector<IRNode *>::const_iterator I = node->args.begin(),
             E = node->args.end(); I != E; ++I, ++i) {
        (*I)->accept(this);
        if (node->function->args[i]->type() != UndefinedTy) {
            assert((*I)->type() == node->function->args[i]->type() &&
                   "Invalid argument type for function call.");
        }
    }
    node->set_type(node->function->type());
}

void TypeChecker::visit(ExternCall *node) {
    if (visited(node) || node->type() != UndefinedTy) return;
    visited_set.insert(node);
    node->set_type(UndefinedTy);
}

void TypeChecker::visit(IORedirection *node) {
    if (node->type() != UndefinedTy) return;
    node->a->accept(this);
    node->b->accept(this);
    node->set_type(UndefinedTy);
}

void TypeChecker::visit(Assignment *node) {
    if (visited(node) || node->type() != UndefinedTy) return;
    visited_set.insert(node);
    node->variable->accept(this);
    node->value->accept(this);
    if (node->variable->type() != UndefinedTy && node->value->type() != UndefinedTy) {
        assert(node->variable->type() == node->value->type() &&
               "Invalid type in assignment.");
    } else {
        node->variable->set_type(node->value->type());
{'fraction_non_alphanumeric': 0.1944561997460855, 'fraction_numerical': 0.00021159542953872197, 'mean_word_length': 3.506196377502383, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 128, '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': '2806009', 'n_tokens_mistral': 1510, 'n_tokens_neox': 1531, 'n_words': 298}