Ejemplo n.º 1
0
Expr*
Parser::on_int(Token tok)
{
  Type const* t = get_integer_type();
  int v = tok.integer_symbol()->value();
  return init<Literal_expr>(tok.location(), t, v);
}
Ejemplo n.º 2
0
Expr*
Elaborator::elaborate(Literal_expr* e)
{
  if (is<Boolean_sym>(e->symbol()))
    e->type(get_boolean_type());
  else if (is<Integer_sym>(e->symbol()))
    e->type(get_integer_type());
  else
    throw std::runtime_error("untyped literal");
  return e;
}
Ejemplo n.º 3
0
// Return the value corresponding to a literal expression.
llvm::Value*
Generator::gen(Literal_expr const* e)
{
  // TODO: Write better type queries.
  //
  // TODO: Write a better interface for values.
  Value v = evaluate(e);
  if (e->type() == get_boolean_type())
    return build.getInt1(v.get_integer());
  if (e->type() == get_integer_type())
    return build.getInt32(v.get_integer());
  else
    throw std::runtime_error("cannot generate function literal");
}
Ejemplo n.º 4
0
// Parse a primary type.
//
//    primary-type -> 'bool'
//                  | 'int'
//                  | 'char'
//                  | id-type
//                  | function-type
//
//    function-type -> '(' type-list ')' '->' type
//
//    type-list -> type | type-list ',' type
Type const*
Parser::primary_type()
{
  // id-type
  if (Token tok = match_if(identifier_tok))
    return on_id_type(tok);

  // bool
  if (match_if(bool_kw))
    return get_boolean_type();

  // char
  if (match_if(char_kw))
    return get_character_type();

  // int
  else if (match_if(int_kw))
    return get_integer_type();

  // function-type
  else if (match_if(lparen_tok)) {
    Type_seq ts;
    while (true) {
      ts.push_back(type());
      if (match_if(comma_tok))
        continue;
      else
        break;
    }
    match(rparen_tok);
    match(arrow_tok);
    Type const* t = type();
    return on_function_type(ts, t);
  }

  // error
  //
  // TODO: Make this a little less vague.
  else
    error("invalid type");
}
Ejemplo n.º 5
0
Expr*
gather(Expr_seq const& subkeys)
{
  // maintain the largest allowable key buffer
  uint512_t buf = 0;

  Evaluator ev;

  // maintain the position to start writing
  int pos = 0;
  for (auto subkey : subkeys) {
    // get the precision of the subkey
    int prec = precision(subkey->type());
    Value const& val = ev.eval(subkey);
    // FIXME: for now we're only dealing with unsigned integer values
    assert(val.is_integer());
    std::stringstream ss;
    ss << val.get_integer().decimal_str();
    uint512_t i = 0;
    ss >> i;
    // shift the integer over by the amount already written
    i = i << pos;
    // add the length of the current integer to the pos
    pos += prec;
    // log-and the integer into the buffer
    buf |= i;
  }

  char* bytes = new char[pos / 8];
  char* key = reinterpret_cast<char*>(&buf);
  std::copy(key, key + (pos / 8), bytes);

  Array_value arr { bytes, (size_t) pos / 8 };
  Type const* z = get_integer_type();
  Expr* n = new Literal_expr(z, arr.len + 1);
  // Create the array type.
  Type const* c = get_character_type();
  Type const* t = get_array_type(c, n);

  return new Literal_expr(t, arr);
}
Ejemplo n.º 6
0
// Build a new string literal. String literals
// are arrays of characters.
Expr*
Parser::on_str(Token tok)
{
  // Build the string value.
  String_sym const* s = tok.string_symbol();
  Array_value v {
     s->value().c_str(),
     s->value().size()
  };

  // Create the extent of the literal array. This is
  // explicitly more than the length of the string,
  // and includes the null character.
  Type const* z = get_integer_type();
  Expr* n = new Literal_expr(z, v.len + 1);

  // Create the array type.
  Type const* c = get_character_type();
  Type const* t = get_array_type(c, n);

  return init<Literal_expr>(tok.location(), t, v);
}
Ejemplo n.º 7
0
// Return the value corresponding to a literal expression.
llvm::Value*
Generator::gen(Literal_expr const* e)
{
  // TODO: Write better type queries.
  //
  // TODO: Write a better interface for values.
  Value v = evaluate(e);
  Type const* t = e->type();
  if (t == get_boolean_type())
    return build.getInt1(v.get_integer());
  if (t == get_character_type())
    return build.getInt8(v.get_integer());
  if (t == get_integer_type())
    return build.getInt32(v.get_integer());

  // FIXME: How should we generate array literals? Are
  // these global constants or are they local alloca
  // objects. Does it depend on context?

  // A string literal produces a new global string constant.
  // and returns a pointer to an array of N characters.
  if (is_string(t)) {
    Array_value a = v.get_array();
    String s = a.get_string();

    // FIXME: This does not unify equivalent strings.
    // Maybe we needt maintain a mapping in order to
    // avoid redunancies.
    auto iter = strings.find(s);
    if (iter == strings.end()) {
      llvm::Value* v = build.CreateGlobalString(s);
      iter = strings.emplace(s, v).first;
    }
    return iter->second;
  }

  else
    throw std::runtime_error("cannot generate function literal");
}
Ejemplo n.º 8
0
// TODO: Default precision depends on configuration.
Integer_type&
Builder::get_uint_type()
{
  return get_integer_type(false, 32);
}
Ejemplo n.º 9
0
// TODO: Default precision depends on configuration.
Integer_type&
Builder::get_int_type()
{
  return get_integer_type(true, 32);
}
Ejemplo n.º 10
0
// TODO: See comments above.
Integer_type&
Builder::get_uint_type(Type_category c, Qualifier_set q)
{
  return get_integer_type(c, false, 32, q);
}
Ejemplo n.º 11
0
Integer_type&
Builder::get_integer_type(bool s, int p, Qualifier_set q)
{
  return get_integer_type(object_type, s, p, q);
}
Ejemplo n.º 12
0
// Parse a primary type.
//
//    primary-type -> 'bool'
//                  | 'int'
//                  | 'char'
//                  | id-type
//                  | function-type
//
//    function-type -> '(' type-list ')' '->' type
//
//    type-list -> type | type-list ',' type
Type const*
Parser::primary_type()
{
  // id-type
  if (Token tok = match_if(identifier_tok))
    return on_id_type(tok);

  // bool
  else if (match_if(bool_kw))
    return get_boolean_type();

  // char
  else if (match_if(char_kw))
    return get_character_type();

  // int
  else if (match_if(int_kw))
    return get_integer_type();

  // uint
  else if (match_if(uint_kw))
    return get_integer_type(false);

  // short
  else if (match_if(short_kw))
    return get_integer_type(16);

  // ushort
  else if (match_if(ushort_kw))
    return get_integer_type(false, 16);

  // long
  else if (match_if(long_kw))
    return get_integer_type(64);

  // ulong
  else if (match_if(ulong_kw))
    return get_integer_type(false, 64);

  // int16
  else if (match_if(int16_kw))
    return get_integer_type(16);

  // uint16
  else if (match_if(uint16_kw))
    return get_integer_type(false, 16);

  // int32
  else if (match_if(int32_kw))
    return get_integer_type();

  // uint32
  else if (match_if(uint32_kw))
    return get_integer_type(false);

  // int64
  else if (match_if(int64_kw))
    return get_integer_type(64);

  // uint64
  else if (match_if(uint64_kw))
    return get_integer_type(false, 64);

  // float
  else if (match_if(float_kw))
      return get_float_type();

  // double
  else if (match_if(double_kw))
      return get_double_type();

  // function-type
  else if (match_if(lparen_tok)) {
    Type_seq ts;
    while (true) {
      ts.push_back(type());
      if (match_if(comma_tok))
        continue;
      else
        break;
    }
    match(rparen_tok);
    match(arrow_tok);
    Type const* t = type();
    return on_function_type(ts, t);
  }

  // error
  //
  // TODO: Make this a little less vague.
  else
    error("invalid type");
}