Exemplo n.º 1
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);
}
Exemplo n.º 2
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");
}
Exemplo n.º 3
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");
}