<commit_before>#include <algorithm>

#include <ast/statement/classdecl.h>
#include <ast/statement/funcdecl.h>
#include <ast/expression/variable.h>

#include <analysis/semanticcontext.h>
#include <analysis/symbol.h>
#include <analysis/symboltable.h>

using namespace std;
using namespace venom::analysis;
using namespace venom::util;

namespace venom {
namespace ast {

struct name_functor_t {
  inline string operator()(ASTExpressionNode* node) const {
    return dynamic_cast<VariableNode*>(node)->getName();
  }
} name_functor;

struct itype_functor {
  itype_functor(SemanticContext* ctx, SymbolTable* st)
    : ctx(ctx), st(st) {}
  inline InstantiatedType* operator()(ASTExpressionNode* node) const {
    VariableNode *vn = dynamic_cast<VariableNode*>(node);
    assert(vn->getExplicitParameterizedTypeString());
    return ctx->instantiateOrThrow(
        st, vn->getExplicitParameterizedTypeString());
  }
  SemanticContext* ctx;
  SymbolTable*     st;
};

void FuncDeclNode::registerSymbol(SemanticContext* ctx) {
  if (symbols->isDefined(name, SymbolTable::Any, false)) {
    throw SemanticViolationException(
        "Function/Method " + name + " already defined");
  }

  // check duplicate param names
  vector<string> names;
  names.resize(params.size());
  transform(params.begin(), params.end(), names.begin(), name_functor);
  if (!is_unique(names.begin(), names.end())) {
    throw SemanticViolationException("Duplicate parameter names");
  }

  // check and instantiate parameter types
  vector<InstantiatedType*> itypes;
  itypes.resize(params.size());
  transform(params.begin(), params.end(),
            itypes.begin(), itype_functor(ctx, symbols));

  // check and instantiate return type
  InstantiatedType* retType;
  if (ret_typename) {
    retType = ctx->instantiateOrThrow(symbols, ret_typename);
  } else {
    // treat no ret type as void type
    retType = InstantiatedType::VoidType;
  }

  // check that ctors dont have non-void return types
  if (locCtx & ASTNode::TopLevelClassBody) {
    ClassDeclNode *cdn = dynamic_cast<ClassDeclNode*>(symbols->getOwner());
    assert(cdn);
    if (cdn->getName() == name &&
        !retType->equals(*InstantiatedType::VoidType)) {
      throw SemanticViolationException(
          "Constructor cannot have non void return type");
    }
  }

  // add symbol to current symtab
  symbols->createFuncSymbol(name, itypes, retType);

  // add parameters to block (child) symtab
  for (size_t i = 0; i < params.size(); i++) {
    VariableNode *vn = dynamic_cast<VariableNode*>(params[i]);
    stmts->getSymbolTable()->createSymbol(
        vn->getName(), itypes[i]);
  }
}

}
}
<commit_msg>WIP: dont allow bad overrides<commit_after>#include <algorithm>

#include <ast/statement/classdecl.h>
#include <ast/statement/funcdecl.h>
#include <ast/expression/variable.h>

#include <analysis/semanticcontext.h>
#include <analysis/symbol.h>
#include <analysis/symboltable.h>

using namespace std;
using namespace venom::analysis;
using namespace venom::util;

namespace venom {
namespace ast {

struct name_functor_t {
  inline string operator()(ASTExpressionNode* node) const {
    return dynamic_cast<VariableNode*>(node)->getName();
  }
} name_functor;

struct itype_functor {
  itype_functor(SemanticContext* ctx, SymbolTable* st)
    : ctx(ctx), st(st) {}
  inline InstantiatedType* operator()(ASTExpressionNode* node) const {
    VariableNode *vn = dynamic_cast<VariableNode*>(node);
    assert(vn->getExplicitParameterizedTypeString());
    return ctx->instantiateOrThrow(
        st, vn->getExplicitParameterizedTypeString());
  }
  SemanticContext* ctx;
  SymbolTable*     st;
};

void FuncDeclNode::registerSymbol(SemanticContext* ctx) {
  if (symbols->isDefined(name, SymbolTable::Any, false)) {
    throw SemanticViolationException(
        "Function/Method " + name + " already defined");
  }

  // check duplicate param names
  vector<string> names;
  names.resize(params.size());
  transform(params.begin(), params.end(), names.begin(), name_functor);
  if (!is_unique(names.begin(), names.end())) {
    throw SemanticViolationException("Duplicate parameter names");
  }

  // check and instantiate parameter types
  vector<InstantiatedType*> itypes;
  itypes.resize(params.size());
  transform(params.begin(), params.end(),
            itypes.begin(), itype_functor(ctx, symbols));

  // check and instantiate return type
  InstantiatedType* retType;
  if (ret_typename) {
    retType = ctx->instantiateOrThrow(symbols, ret_typename);
  } else {
    // treat no ret type as void type
    retType = InstantiatedType::VoidType;
  }


  if (locCtx & ASTNode::TopLevelClassBody) {
    ClassDeclNode *cdn = dynamic_cast<ClassDeclNode*>(symbols->getOwner());
    assert(cdn);

    // check that ctors dont have non-void return types
    if (cdn->getName() == name &&
        !retType->equals(*InstantiatedType::VoidType)) {
      throw SemanticViolationException(
          "Constructor cannot have non void return type");
    }

    // check that type-signature matches for overrides
    FuncSymbol *fs = symbols->findFuncSymbol(name, true);
    if (fs && fs->isMethod()) {
      InstantiatedType *overrideType =
        fs->bind(ctx, vector<InstantiatedType*>());

      vector<InstantiatedType*> fparams(itypes);
      fparams.push_back(retType);
      InstantiatedType *myType =
        Type::FuncTypes.at(itypes.size())->instantiate(ctx, fparams);

      if (!overrideType->equals(*myType)) {
        throw SemanticViolationException(
            "Overriding type signatures do not match: Cannot override method " +
            name + " of type " + overrideType->stringify() +
            " with type " + myType->stringify());
      }
    }
  }

  // add symbol to current symtab
  symbols->createFuncSymbol(name, itypes, retType);

  // add parameters to block (child) symtab
  for (size_t i = 0; i < params.size(); i++) {
    VariableNode *vn = dynamic_cast<VariableNode*>(params[i]);
    stmts->getSymbolTable()->createSymbol(
        vn->getName(), itypes[i]);
  }
}

}
}

{'fraction_non_alphanumeric': 0.13258389816498595, 'fraction_numerical': 0.00033063316250619935, 'mean_word_length': 4.067001675041876, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 64, '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': '944748', 'n_tokens_mistral': 1876, 'n_tokens_neox': 1837, 'n_words': 417}