Example #1
0
std::size_t
hash_value(Call_expr const& e)
{
  std::size_t h = hash_type(e);
  boost::hash_combine(h, e.function());
  boost::hash_combine(h, e.arguments());
  return h;
}
Example #2
0
Value
Evaluator::evaluate_call(Call_expr const& e)
{
  Value v = evaluate(e.function());
  Function_decl const& f = *v.get_function();

  // Get the function's definition.
  if (!f.is_definition())
    throw Internal_error("function '{}' is not defined", f.name());

  // There should probably be a body for the function.
  //
  // FIXME: What if the function is = default. How do we determine
  // what that behavior should be? Synthesize a new kind of defintion
  // that explicitly performs that behavior?
  //
  // TODO: It would be more elegant to simply dispatch on the
  // definition rather than filter it here.
  Function_def const* def = as<Function_def>(&f.definition());
  if (!def)
    lingo_unimplemented();

  // Each parameter is declared as a local variable within the
  // function.
  Enter_frame frame(*this);
  Expr_list const& args = e.arguments();
  Decl_list const& parms = f.parameters();
  auto ai = args.begin();
  auto pi = parms.begin();
  while (ai != args.end() && pi != parms.end()) {
    Expr const& arg = *ai;
    Decl const& parm = *pi;

    // TODO: Parameters are copy-initialized. Reuse initialization
    // here, insted of this kind of direct storage. Use alloca
    // and then dispatch to the initializer.
    store(parm, evaluate(arg));
  }

  // Evaluate the function definition.
  //
  // TODO: Check result in case we've thrown an exception.
  //
  // FIXME: Failure to evaluate is a translation error, not
  // an internal error.
  Value result;
  Control ctl = evaluate(def->statement(), result);
  if (ctl != return_ctl)
    throw Evaluation_error("function evaluation failed");
  return result;
}