Exemple #1
0
// Parse a template declaration.
//
//    tempate-declaration:
//      'template' '<' template-parameter-list '>' [requires-clause] declaration
//
// FIXME: Support explicit template instantiations in one way or
// another.
Decl&
Parser::template_declaration()
{
  #if 0
  require(tk::template_tok);

  // Build a psuedo-scope.
  //
  // FIXME: Merge this with template parameter scope. I don't think
  // that it's serving a very useful purpose.
  // Template_scope& tmp = cxt.make_template_scope();
  Enter_scope tscope(cxt, tmp);

  // TODO: Allow >> to close the template parameter list in the
  // case of default template arguments.
  Enter_template_parameter_scope pscope(cxt);
  match(tk::lt_tok);
  tmp.parms = template_parameter_list();
  match(tk::gt_tok);

  // Parse the optional requires clause, followed by the parameterized
  // declaration.
  if (tk::next_token_is(tk::requires_tok)) {
    // TODO: How are dependent names resolved in a requires clause?
    tmp.cons = &requires_clause();
    // Enter_scope cscope(cxt, cxt.make_constrained_scope(*tmp.cons));
    Parsing_template save(*this, &tmp.parms, tmp.cons);
    return declaration();
  } else {
    Parsing_template save(*this, &tmp.parms);
    return declaration();
  }
  #endif
  lingo_unreachable();
}
Exemple #2
0
Decl&
specialize_function(Context& cxt, Template_decl& tmp, Function_decl& d, Substitution& sub)
{
#if 0
  // Create the specialization name.
  Name& n = cxt.get_template_id(tmp, sub.arguments());

  // Substitute through parameters.
  //
  // TODO: I think I need to re-establish name bindings during substitution
  // because we are going to be resolving types at the same time. This
  // means that I am going to have to move scoping facilities from the
  // parser to the context (which makes some sense).
  Decl_list parms;
  for (Decl& p1 : d.parameters()) {
    Decl& p2 = substitute(cxt, p1, sub);
    parms.push_back(p2);
  }

  // Substitute through the return type.
  Type& ret = substitute(cxt, d.return_type(), sub);

  // FIXME: I've just re-attached an uninstantiated definition
  // to the declaration. That is going to be a problem.
  // return cxt.make_function_declaration(n, parms, ret, d.definition());
#endif
  lingo_unreachable();
}
Exemple #3
0
Def&
Parser::on_deleted_definition(Decl& d)
{
  // Def& def = build.make_deleted_definition();
  // return define_entity(d, def);
  lingo_unreachable();
}
Exemple #4
0
Def&
Parser::on_defaulted_definition(Decl& d)
{
  // Def& def = build.make_defaulted_definition();
  // return define_function(d, def);
  lingo_unreachable();
}
Exemple #5
0
// Parse a directive sequence.
//
//    directive-seq
//      'type' expression ';'
//      'evaluate' expression ';'
//      'resolve' postscript-expression ';'
//      'instantiate' template-id ';'
//      'satisfy' check-expr ';'
//      'order' '.' 'template' template-id template-id ';'
//      'order' '.' 'concept' concept-id concept-id ';'
//      'inspect.expr' expression ';'
void
directive_seq(Parser& p)
{
  // Parse the directive sequence as if in the global namespace.
  Enter_scope scope(p.cxt, p.cxt.global_namespace());
  while (p.peek()) {
    // TODO: We know that the next token is an identifier.
    // There is a more efficient way of doing this.
    if (p.next_token_is("type"))
      type_directive(p);
    else if (p.next_token_is("evaluate"))
      evaluate_directive(p);
    else if (p.next_token_is("resolve"))
      resolve_directive(p);
    else if (p.next_token_is("instantiate"))
      instantiate_directive(p);
    else if (p.next_token_is("satisfy"))
      satisfy_directive(p);
    else if (p.next_token_is("order"))
      order_directive(p);
    else if (p.next_token_is("inspect"))
      inspect_directive(p);
    else
      lingo_unreachable(); // FIXME: Actually diagnose an error.
  }
}
Exemple #6
0
char const*
get_spelling(Binary_op op)
{
  switch (op) {
    case num_add_op: return "+";
    case num_sub_op: return "-";
    case num_mul_op: return "*";
    case num_div_op: return "/";
    case num_mod_op: return "%";
    case bit_and_op: return "&";
    case bit_or_op: return "|";
    case bit_xor_op: return "^";
    case bit_lsh_op: return "<<";
    case bit_rsh_op: return ">>";
    case rel_eq_op: return "==";
    case rel_ne_op: return "!=";
    case rel_lt_op: return "<";
    case rel_gt_op: return ">";
    case rel_le_op: return "<=";
    case rel_ge_op: return ">=";
    case log_and_op: return "&&";
    case log_or_op: return "||";
  }
  lingo_unreachable("invalid binary operator ({})", (int)op);
}
Exemple #7
0
// Parse a requires expression.
//
//    requires-expression:
//      'requires' ['<' template-parameter-list '>'] ['(' parameter-list ')'] requires-body
//
Expr&
Parser::requires_expression()
{
  lingo_unreachable();

  // Token tok = require(tk::requires_tok);

  // // Match template parameter.
  // //
  // // TODO: Introduce a new scope.
  // Decl_list tparms;
  // if (match_if(tk::lt_tok)) {
  //   tparms = template_parameter_list();
  //   match(tk::gt_tok);
  // }

  // // Parse parameters in a new block scope.
  // // Enter_scope scope(cxt, cxt.make_requires_scope());
  // Decl_list parms;
  // if (match_if(tk::lparen_tok)) {
  //   parms = parameter_list();
  //   match(tk::rparen_tok);
  // }

  // match(tk::lbrace_tok);
  // Req_list reqs = usage_seq();
  // match(tk::rbrace_tok);

  // return on_requires_expression(tok, tparms, parms, reqs);
}
Exemple #8
0
// Return a converted template argument.
Term&
initialize_template_parameter(Context& cxt,
                              Decl_iter p0,
                              Decl_iter& pi,
                              Term_iter a0,
                              Term_iter& ai)
{
  // TODO: Trap kind/type errors and emit good diagnostics.
  Term* c;
  if (Type_parm* p = as<Type_parm>(&*pi))
    c = &initialize_type_template_parameter(cxt, *p, *ai);
  else if (Value_parm* p = as<Value_parm>(&*pi))
    c = &initialize_value_template_parameter(cxt, *p, *ai);
  else if (Template_parm* p = as<Template_parm>(&*pi))
    c = &initialize_template_template_parameter(cxt, *p, *ai);
  else
    lingo_unreachable();

  // TODO: Handle parameter packs. How would these be
  // represented? Note that this isn't just the non-advancement
  // of the parameter, but the packing of subsequent arguments
  // into a new pack argument.
  ++pi;
  ++ai;

  return *c;
}
Exemple #9
0
// Parse a declaration.
//
//    declaration:
//      [specifier-seq] basic-declaration
//
//    basic-declaration:
//      variable-declaration
//      function-declaration
//      type-declaration
//      concept-declaration
Decl&
Parser::declaration()
{
  // Parse and cache the specifier sequences.
  specifier_seq();

  switch (lookahead()) {
    case tk::var_tok:
      return variable_declaration();

    case tk::def_tok:
      return function_declaration();

    case tk::class_tok:
      return class_declaration();

    case tk::concept_tok:
      lingo_unreachable();
    case tk::super_tok:
      return super_declaration();
    default:
      break;
  }
  throw Syntax_error("invalid declaration");
}
Exemple #10
0
// Construct a reference to an unresolved (overloaded) member.
static Expr&
make_mem_overload_ref(Context& cxt, Expr& obj, Name& name, Decl_list&& ds)
{
  lingo_unreachable();

  // return cxt.make_reference(obj, name, std::move(ds));
}
Exemple #11
0
// Assuming the type of e1 is untested and e2 has floating point
// type, convert to the most precise floating point type.
Expr_pair
convert_to_common_float(Context& cxt, Expr& e1, Expr& e2)
{
  Float_type& f2 = cast<Float_type>(e2.type());

  // If e1 has float type, convert to the most precise type.
  if (has_floating_point_type(e1)) {
    Float_type& f1 = cast<Float_type>(e1.type());
    if (f1.precision() < f2.precision()) {
      Expr& c = convert_to_wider_float(cxt, e1, f2);
      return {c, e2};
    }
    if (f2.precision() < f1.precision()) {
      Expr& c = convert_to_wider_float(cxt, e2, f1);
      return {e1, c};
    }
    lingo_unreachable();
  }

  // If e1 has integer type, convert to e2.
  if (has_integer_type(e1)) {
    Expr& c = convert_integer_to_float(cxt, e1, f2);
    return {c, e2};
  }

  error(cxt, "no floating point conversions for '{}' and '{}'", e1, e2);
  throw Type_error();
}
Exemple #12
0
Def&
Parser::on_function_definition(Decl& d, Stmt& s)
{
  // Def& def = build.make_function_definition(s);
  // return define_function(d, def);
  lingo_unreachable();
}
Exemple #13
0
Decl&
Parser::on_concept_declaration(Token, Name& n, Decl_list& ps)
{
  lingo_unreachable();
  // Decl& decl = build.make_concept(n, ps);
  // declare(cxt, current_scope(), decl);
  // return decl;
}
Exemple #14
0
Decl&
Parser::on_super_declaration(Name& n, Type& t)
{
  lingo_unreachable();
  // Decl& d = cxt.make_super_declaration(t);
  // declare(cxt, d);
  // return d;
}
Exemple #15
0
void
instantiate_directive(Parser& p)
{
  p.require("instantiate");
  // Name& n = p.template_id();
  // Actually show the instantated definition.
  lingo_unreachable();
}
Exemple #16
0
Def&
Parser::on_concept_definition(Decl& decl, Req_list& ds)
{
  lingo_unreachable();
  // Def& def = build.make_concept_definition(ds);
  // define_concept(decl, def);
  // return def;
}
Exemple #17
0
Def&
Parser::on_concept_definition(Decl& decl, Expr& e)
{
  lingo_unreachable();
  // Def& def = build.make_expression_definition(e);
  // define_concept(decl, def);
  // return def;
}
Exemple #18
0
// Update `d` with the initializer `e`.
static inline void
initialize_declaration(Decl& d, Expr& e)
{
  if (Variable_decl* var = as<Variable_decl>(&d))
    var->init = &e;
  else
    lingo_unreachable();
}
Exemple #19
0
Decl&
Parser::on_type_template_parameter(Name& n, Type& t)
{
  lingo_unreachable();
  // Decl& parm = build.make_type_parameter(n, t);
  // declare(cxt, current_scope(), parm);
  // return parm;
}
Exemple #20
0
Expr&
Parser::subscript_expression(Expr& e)
{
  require(tk::lbracket_tok);
  // Expr& index = expression();
  match(tk::rbracket_tok);
  lingo_unreachable();
}
Exemple #21
0
// FIXME: This is dumb. We should have a base class that contributes
// a type to the declaration hiearchy (Typed_decl).
static inline Type&
declared_type(Decl& d)
{
  if (Variable_decl* var = as<Variable_decl>(&d))
    return var->type();

  // We can initialize other things too.
  lingo_unreachable();
}
Exemple #22
0
// Perform qualified lookup to resolve the declaration referred to by obj.n.
Expr&
make_member_reference(Context& cxt, Expr& obj, Simple_id& name)
{
  Type& type = obj.type();
  Decl_list decls = qualified_lookup(cxt, type, name);
  if (decls.size() == 1)
    return make_member_reference(cxt, obj, decls.front());
  lingo_unreachable();
}
Exemple #23
0
void
resolve_directive(Parser& p)
{
  p.require("reolve");
  Expr& e = p.postfix_expression();
  std::cout << e << '\n';

  // TODO: Actually show which function was resolved.
  lingo_unreachable();
}
Exemple #24
0
std::ostream&
operator<<(std::ostream& os, Validation v)
{
  switch (v) {
  case valid_proof: return os << "valid";
  case invalid_proof: return os << "invalid";
  case incomplete_proof: return os << "incomplete";
  default: lingo_unreachable();
  }
}
Exemple #25
0
Expr const*
Parser::on_unary(Token tok, Expr const* e)
{
  Location loc = tok.location();
  switch (tok.kind()) {
    case plus_tok: return new Pos(loc, e);
    case minus_tok: return new Neg(loc, e);
    default: break;
  }
  lingo_unreachable("invalid unary operator", tok.spelling());
}
Exemple #26
0
// FIXME: How do I compare two templates with the same name?
// Just give them different names?
void
order_template_directive(Parser& p)
{
  // p.require(template_tok);
  // Name& n1 = p.template_id();
  // Name& n2 = p.template_id();

  // TODO: Resolve the function templates referred to by these
  // ids and determine which is more specialized.
  lingo_unreachable();
}
Exemple #27
0
char const*
get_spelling(Unary_op op)
{
  switch (op) {
    case num_neg_op: return "-";
    case num_pos_op: return "+";
    case bit_not_op: return "~";
    case log_not_op: return "!";
  }
  lingo_unreachable("invalid unary operator ({})", (int)op);
}
Exemple #28
0
void
inspect_directive(Parser& p)
{
  p.require("inspect");
  p.match(dot_tok);
  if (p.next_token_is("expression"))
    return inspect_expression_directive(p);

  // FIXME: Be a little more polite.
  lingo_unreachable();
}
Exemple #29
0
// Synthesize a unique type, value, or template from a corresponding
// template parameter.
//
// TODO: Handle template parameter packs.
Term&
synthesize_template_argument(Context& cxt, Decl& parm)
{
  if (Type_parm* t = as<Type_parm>(&parm))
    return synthesize_template_argument(cxt, *t);
  if (Value_parm* e = as<Value_parm>(&parm))
    return synthesize_template_argument(cxt, *e);
  if (Template_parm* x = as<Template_parm>(&parm))
    return synthesize_template_argument(cxt, *x);
  lingo_unreachable();
}
Exemple #30
0
Term&
substitute(Context& cxt, Term& x, Substitution& sub)
{
  if (Type* t = as<Type>(&x))
    return substitute(cxt, *t, sub);
  if (Expr* e = as<Expr>(&x))
    return substitute(cxt, *e, sub);
  if (Decl* d = as<Decl>(&x))
    return substitute(cxt, *d, sub);
  lingo_unreachable();
}