Example #1
0
ValuePtr BWhile::Infer(TypeChecker& checker, const vector<ExprPtr>& args)
{
  assert(args.size() == 2);

  auto& cond = args[0];
  auto& body = args[1];

  checker.Visit(cond.get());
  if(!cond->value)
    return {};

  TypeSubst condSubst;
  checker.subst.swap(condSubst);

  bool lastInsideLoop = checker.insideLoop;
  checker.insideLoop = true;
  checker.Visit(body.get());
  checker.insideLoop = lastInsideLoop;
  if(!body->value)
    return {};

  Compose(condSubst, checker.subst);
  Compose(Unify(*cond->value->type, *BooleanType), checker.subst);

  return VoidValue; // TODO should a while yield a value?
}
Example #2
0
ValuePtr BArithmetic<Operation>::Infer(TypeChecker& checker, const vector<ExprPtr>& args)
{
  assert(args.size() == 2);

  auto& left = args[0];
  auto& right = args[1];

  checker.Visit(left.get());
  if(!left->value)
    return {};

  TypeSubst leftSubst;
  checker.subst.swap(leftSubst);

  checker.Visit(right.get());
  if(!right->value)
    return {};

  Compose(leftSubst, checker.subst);
  Compose(Unify(*left->value->type, *right->value->type), checker.subst);

  auto type = left->value->type.get();
  if(!isa<TInteger>(type) && !isa<TFloat>(type)) {
    Error() << "Arithmetic operation requires float or integer operands";
    return {};
  }

  ValuePtr value = new VTemporary;
  value->type = ResultType<typename Operation::IsCompare>(type);
  return value;
}
Example #3
0
ValuePtr BIf::Infer(TypeChecker& checker, const vector<ExprPtr>& args)
{
  assert(args.size() >= 2 && args.size() % 2 == 0);

  // conditions
  for(size_t i = 0; i < args.size(); i += 2)
  {
    TypeSubst lastSubst;
    checker.subst.swap(lastSubst);

    checker.Visit(args[i].get());
    if(!args[i]->value)
      return {};

    Compose(lastSubst, checker.subst);
    Compose(Unify(*args[i]->value->type, *BooleanType), checker.subst);
  }

  // clauses
  for(size_t i = 1; i < args.size(); i += 2)
  {
    TypeSubst lastSubst;
    checker.subst.swap(lastSubst);

    checker.Visit(args[i].get());
    if(!args[i]->value)
      return {};

    Compose(lastSubst, checker.subst);
    if(i != 1)
      Compose(Unify(*args[i]->value->type, *args[i - 2]->value->type), checker.subst);
  }

  for(auto& e : args)
    e->value->type = xra::Apply(checker.subst, *e->value->type);

  if(args.size() == 2)
    return VoidValue;

  ValuePtr value = new VTemporary;
  value->type = args[1]->value->type;
  return value;
}
Example #4
0
ValuePtr BModule::Infer(TypeChecker& checker, const vector<ExprPtr>& args)
{
  auto module = static_cast<EVariable&>(*args[0]).name;
  module = AbsoluteModule(checker.moduleName, module);

  checker.moduleName.swap(module);
  checker.Visit(args[1].get());
  checker.moduleName.swap(module);

  return VoidValue;
}
Example #5
0
ValuePtr BAssign::Infer(TypeChecker& checker, const vector<ExprPtr>& args)
{
  assert(args.size() == 2);

  auto& left = args[0];
  auto& right = args[1];

  checker.Visit(right.get());
  if(!right->value)
    return {};

  TypeSubst rightSubst;
  checker.subst.swap(rightSubst);

  // if the left side is a plain variable not in the environment, create a fresh local
  if(isa<EVariable>(left.get()))
  {
    auto& name = static_cast<EVariable&>(*left).name;
    if(!checker.env[name]) {
      left->value = new VLocal;
      left->value->type = MakeTypeVar();
      checker.env.AddValue(name, left->value);
    }
  }

  if(!left->value)
  {
    checker.Visit(left.get());
    if(!left->value)
      return {};
  }

  Compose(rightSubst, checker.subst);

  auto unifySubst = Unify(*left->value->type, *right->value->type);
  left->value->type = xra::Apply(unifySubst, *left->value->type);
  Compose(unifySubst, checker.subst);

  return left->value;
}
Example #6
0
ValuePtr BUsing::Infer(TypeChecker& checker, const vector<ExprPtr>& args)
{
  auto module = static_cast<EVariable&>(*args[0]).name;
  module = AbsoluteModule(checker.moduleName, module);

  if(!checker.usingModules.insert(module).second) {
    Error() << "duplicate using: " << module;
    return {};
  }
  checker.Visit(args[1].get());
  checker.usingModules.erase(module);

  return VoidValue;
}
Example #7
0
ValuePtr BSequence::Infer(TypeChecker& checker, const vector<ExprPtr>& args)
{
  for(auto& e : args)
  {
    TypeSubst lastSubst;
    checker.subst.swap(lastSubst);

    checker.Visit(e.get());
    if(!e->value)
      return {};

    Compose(lastSubst, checker.subst);
  }

  return args.back()->value;
}
Example #8
0
ValuePtr BReturn::Infer(TypeChecker& checker, const vector<ExprPtr>& args)
{
  assert(args.size() == 0 || args.size() == 1);

  TypePtr rty = VoidType;
  if(!args.empty()) {
    checker.Visit(args[0].get());
    if(!args[0]->value)
      return {};
    rty = args[0]->value->type;
  }

  if(checker.returnType)
    Compose(Unify(*rty, *checker.returnType), checker.subst);
  else
    checker.returnType = rty;

  return VoidValue;
}