compiler: Change alias handling, change rune alias to int32.
From-SVN: r183374
This commit is contained in:
parent
4787ac51eb
commit
fb3f3aa2db
@ -338,6 +338,8 @@ Export::register_builtin_types(Gogo* gogo)
|
||||
this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
|
||||
this->register_builtin_type(gogo, "string", BUILTIN_STRING);
|
||||
this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
|
||||
this->register_builtin_type(gogo, "byte", BUILTIN_BYTE);
|
||||
this->register_builtin_type(gogo, "rune", BUILTIN_RUNE);
|
||||
}
|
||||
|
||||
// Register one builtin type in the export table.
|
||||
@ -352,10 +354,14 @@ Export::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code)
|
||||
go_assert(ins.second);
|
||||
|
||||
// We also insert the underlying type. We can see the underlying
|
||||
// type at least for string and bool.
|
||||
Type* real_type = named_object->type_value()->real_type();
|
||||
ins = this->type_refs_.insert(std::make_pair(real_type, code));
|
||||
go_assert(ins.second);
|
||||
// type at least for string and bool. We skip the type aliases byte
|
||||
// and rune here.
|
||||
if (code != BUILTIN_BYTE && code != BUILTIN_RUNE)
|
||||
{
|
||||
Type* real_type = named_object->type_value()->real_type();
|
||||
ins = this->type_refs_.insert(std::make_pair(real_type, code));
|
||||
go_assert(ins.second);
|
||||
}
|
||||
}
|
||||
|
||||
// Class Export::Stream.
|
||||
|
@ -40,8 +40,10 @@ enum Builtin_code
|
||||
BUILTIN_COMPLEX64 = -17,
|
||||
BUILTIN_COMPLEX128 = -18,
|
||||
BUILTIN_ERROR = -19,
|
||||
BUILTIN_BYTE = -20,
|
||||
BUILTIN_RUNE = -21,
|
||||
|
||||
SMALLEST_BUILTIN_CODE = -19
|
||||
SMALLEST_BUILTIN_CODE = -21
|
||||
};
|
||||
|
||||
// This class manages exporting Go declarations. It handles the main
|
||||
|
@ -1740,9 +1740,10 @@ Expression::make_string(const std::string& val, Location location)
|
||||
class Integer_expression : public Expression
|
||||
{
|
||||
public:
|
||||
Integer_expression(const mpz_t* val, Type* type, Location location)
|
||||
Integer_expression(const mpz_t* val, Type* type, bool is_character_constant,
|
||||
Location location)
|
||||
: Expression(EXPRESSION_INTEGER, location),
|
||||
type_(type)
|
||||
type_(type), is_character_constant_(is_character_constant)
|
||||
{ mpz_init_set(this->val_, *val); }
|
||||
|
||||
static Expression*
|
||||
@ -1782,8 +1783,14 @@ class Integer_expression : public Expression
|
||||
|
||||
Expression*
|
||||
do_copy()
|
||||
{ return Expression::make_integer(&this->val_, this->type_,
|
||||
this->location()); }
|
||||
{
|
||||
if (this->is_character_constant_)
|
||||
return Expression::make_character(&this->val_, this->type_,
|
||||
this->location());
|
||||
else
|
||||
return Expression::make_integer(&this->val_, this->type_,
|
||||
this->location());
|
||||
}
|
||||
|
||||
void
|
||||
do_export(Export*) const;
|
||||
@ -1796,6 +1803,8 @@ class Integer_expression : public Expression
|
||||
mpz_t val_;
|
||||
// The type so far.
|
||||
Type* type_;
|
||||
// Whether this is a character constant.
|
||||
bool is_character_constant_;
|
||||
};
|
||||
|
||||
// Return an integer constant value.
|
||||
@ -1817,7 +1826,12 @@ Type*
|
||||
Integer_expression::do_type()
|
||||
{
|
||||
if (this->type_ == NULL)
|
||||
this->type_ = Type::make_abstract_integer_type();
|
||||
{
|
||||
if (this->is_character_constant_)
|
||||
this->type_ = Type::make_abstract_character_type();
|
||||
else
|
||||
this->type_ = Type::make_abstract_integer_type();
|
||||
}
|
||||
return this->type_;
|
||||
}
|
||||
|
||||
@ -1835,7 +1849,12 @@ Integer_expression::do_determine_type(const Type_context* context)
|
||||
|| context->type->complex_type() != NULL))
|
||||
this->type_ = context->type;
|
||||
else if (!context->may_be_abstract)
|
||||
this->type_ = Type::lookup_integer_type("int");
|
||||
{
|
||||
if (this->is_character_constant_)
|
||||
this->type_ = Type::lookup_integer_type("int32");
|
||||
else
|
||||
this->type_ = Type::lookup_integer_type("int");
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if the integer VAL fits in the range of the type TYPE.
|
||||
@ -1950,6 +1969,8 @@ void
|
||||
Integer_expression::do_export(Export* exp) const
|
||||
{
|
||||
Integer_expression::export_integer(exp, this->val_);
|
||||
if (this->is_character_constant_)
|
||||
exp->write_c_string("'");
|
||||
// A trailing space lets us reliably identify the end of the number.
|
||||
exp->write_c_string(" ");
|
||||
}
|
||||
@ -2013,6 +2034,10 @@ Integer_expression::do_import(Import* imp)
|
||||
else if (num.find('.') == std::string::npos
|
||||
&& num.find('E') == std::string::npos)
|
||||
{
|
||||
bool is_character_constant = (!num.empty()
|
||||
&& num[num.length() - 1] == '\'');
|
||||
if (is_character_constant)
|
||||
num = num.substr(0, num.length() - 1);
|
||||
mpz_t val;
|
||||
if (mpz_init_set_str(val, num.c_str(), 10) != 0)
|
||||
{
|
||||
@ -2020,7 +2045,11 @@ Integer_expression::do_import(Import* imp)
|
||||
num.c_str());
|
||||
return Expression::make_error(imp->location());
|
||||
}
|
||||
Expression* ret = Expression::make_integer(&val, NULL, imp->location());
|
||||
Expression* ret;
|
||||
if (is_character_constant)
|
||||
ret = Expression::make_character(&val, NULL, imp->location());
|
||||
else
|
||||
ret = Expression::make_integer(&val, NULL, imp->location());
|
||||
mpz_clear(val);
|
||||
return ret;
|
||||
}
|
||||
@ -2043,16 +2072,27 @@ Integer_expression::do_import(Import* imp)
|
||||
void
|
||||
Integer_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
|
||||
{
|
||||
if (this->is_character_constant_)
|
||||
ast_dump_context->ostream() << '\'';
|
||||
Integer_expression::export_integer(ast_dump_context, this->val_);
|
||||
if (this->is_character_constant_)
|
||||
ast_dump_context->ostream() << '\'';
|
||||
}
|
||||
|
||||
// Build a new integer value.
|
||||
|
||||
Expression*
|
||||
Expression::make_integer(const mpz_t* val, Type* type,
|
||||
Location location)
|
||||
Expression::make_integer(const mpz_t* val, Type* type, Location location)
|
||||
{
|
||||
return new Integer_expression(val, type, location);
|
||||
return new Integer_expression(val, type, false, location);
|
||||
}
|
||||
|
||||
// Build a new character constant value.
|
||||
|
||||
Expression*
|
||||
Expression::make_character(const mpz_t* val, Type* type, Location location)
|
||||
{
|
||||
return new Integer_expression(val, type, true, location);
|
||||
}
|
||||
|
||||
// Floats.
|
||||
|
@ -164,6 +164,11 @@ class Expression
|
||||
static Expression*
|
||||
make_string(const std::string&, Location);
|
||||
|
||||
// Make a character constant expression. TYPE should be NULL for an
|
||||
// abstract type.
|
||||
static Expression*
|
||||
make_character(const mpz_t*, Type*, Location);
|
||||
|
||||
// Make a constant integer expression. TYPE should be NULL for an
|
||||
// abstract type.
|
||||
static Expression*
|
||||
|
@ -58,8 +58,9 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int int_type_size,
|
||||
RUNTIME_TYPE_KIND_INT8));
|
||||
this->add_named_type(Type::make_integer_type("int16", false, 16,
|
||||
RUNTIME_TYPE_KIND_INT16));
|
||||
this->add_named_type(Type::make_integer_type("int32", false, 32,
|
||||
RUNTIME_TYPE_KIND_INT32));
|
||||
Named_type* int32_type = Type::make_integer_type("int32", false, 32,
|
||||
RUNTIME_TYPE_KIND_INT32);
|
||||
this->add_named_type(int32_type);
|
||||
this->add_named_type(Type::make_integer_type("int64", false, 64,
|
||||
RUNTIME_TYPE_KIND_INT64));
|
||||
|
||||
@ -82,23 +83,22 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int int_type_size,
|
||||
RUNTIME_TYPE_KIND_INT);
|
||||
this->add_named_type(int_type);
|
||||
|
||||
// "byte" is an alias for "uint8". Construct a Named_object which
|
||||
// points to UINT8_TYPE. Note that this breaks the normal pairing
|
||||
// in which a Named_object points to a Named_type which points back
|
||||
// to the same Named_object.
|
||||
Named_object* byte_type = this->declare_type("byte", loc);
|
||||
byte_type->set_type_value(uint8_type);
|
||||
uint8_type->integer_type()->set_is_byte();
|
||||
|
||||
// "rune" is an alias for "int".
|
||||
Named_object* rune_type = this->declare_type("rune", loc);
|
||||
rune_type->set_type_value(int_type);
|
||||
int_type->integer_type()->set_is_rune();
|
||||
|
||||
this->add_named_type(Type::make_integer_type("uintptr", true,
|
||||
pointer_size,
|
||||
RUNTIME_TYPE_KIND_UINTPTR));
|
||||
|
||||
// "byte" is an alias for "uint8".
|
||||
uint8_type->integer_type()->set_is_byte();
|
||||
Named_object* byte_type = Named_object::make_type("byte", NULL, uint8_type,
|
||||
loc);
|
||||
this->add_named_type(byte_type->type_value());
|
||||
|
||||
// "rune" is an alias for "int32".
|
||||
int32_type->integer_type()->set_is_rune();
|
||||
Named_object* rune_type = Named_object::make_type("rune", NULL, int32_type,
|
||||
loc);
|
||||
this->add_named_type(rune_type->type_value());
|
||||
|
||||
this->add_named_type(Type::make_named_bool_type());
|
||||
|
||||
this->add_named_type(Type::make_named_string_type());
|
||||
@ -3830,7 +3830,12 @@ Variable::type_from_range(Expression* expr, bool get_index_type,
|
||||
return t->deref()->array_type()->element_type();
|
||||
}
|
||||
else if (t->is_string_type())
|
||||
return Type::lookup_integer_type("int");
|
||||
{
|
||||
if (get_index_type)
|
||||
return Type::lookup_integer_type("int");
|
||||
else
|
||||
return Type::lookup_integer_type("int32");
|
||||
}
|
||||
else if (t->map_type() != NULL)
|
||||
{
|
||||
if (get_index_type)
|
||||
|
@ -696,6 +696,8 @@ Import::register_builtin_types(Gogo* gogo)
|
||||
this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
|
||||
this->register_builtin_type(gogo, "string", BUILTIN_STRING);
|
||||
this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
|
||||
this->register_builtin_type(gogo, "byte", BUILTIN_BYTE);
|
||||
this->register_builtin_type(gogo, "rune", BUILTIN_RUNE);
|
||||
}
|
||||
|
||||
// Register a single builtin type.
|
||||
|
@ -163,7 +163,8 @@ Token::~Token()
|
||||
void
|
||||
Token::clear()
|
||||
{
|
||||
if (this->classification_ == TOKEN_INTEGER)
|
||||
if (this->classification_ == TOKEN_INTEGER
|
||||
|| this->classification_ == TOKEN_CHARACTER)
|
||||
mpz_clear(this->u_.integer_value);
|
||||
else if (this->classification_ == TOKEN_FLOAT
|
||||
|| this->classification_ == TOKEN_IMAGINARY)
|
||||
@ -190,6 +191,7 @@ Token::Token(const Token& tok)
|
||||
case TOKEN_OPERATOR:
|
||||
this->u_.op = tok.u_.op;
|
||||
break;
|
||||
case TOKEN_CHARACTER:
|
||||
case TOKEN_INTEGER:
|
||||
mpz_init_set(this->u_.integer_value, tok.u_.integer_value);
|
||||
break;
|
||||
@ -229,6 +231,7 @@ Token::operator=(const Token& tok)
|
||||
case TOKEN_OPERATOR:
|
||||
this->u_.op = tok.u_.op;
|
||||
break;
|
||||
case TOKEN_CHARACTER:
|
||||
case TOKEN_INTEGER:
|
||||
mpz_init_set(this->u_.integer_value, tok.u_.integer_value);
|
||||
break;
|
||||
@ -264,6 +267,10 @@ Token::print(FILE* file) const
|
||||
case TOKEN_STRING:
|
||||
fprintf(file, "quoted string \"%s\"", this->u_.string_value->c_str());
|
||||
break;
|
||||
case TOKEN_CHARACTER:
|
||||
fprintf(file, "character ");
|
||||
mpz_out_str(file, 10, this->u_.integer_value);
|
||||
break;
|
||||
case TOKEN_INTEGER:
|
||||
fprintf(file, "integer ");
|
||||
mpz_out_str(file, 10, this->u_.integer_value);
|
||||
@ -1320,7 +1327,7 @@ Lex::gather_character()
|
||||
|
||||
Location location = this->location();
|
||||
this->lineoff_ = p + 1 - this->linebuf_;
|
||||
Token ret = Token::make_integer_token(val, location);
|
||||
Token ret = Token::make_character_token(val, location);
|
||||
mpz_clear(val);
|
||||
return ret;
|
||||
}
|
||||
|
@ -70,6 +70,8 @@ class Token
|
||||
TOKEN_STRING,
|
||||
// Token is an operator.
|
||||
TOKEN_OPERATOR,
|
||||
// Token is a character constant.
|
||||
TOKEN_CHARACTER,
|
||||
// Token is an integer.
|
||||
TOKEN_INTEGER,
|
||||
// Token is a floating point number.
|
||||
@ -135,6 +137,16 @@ class Token
|
||||
return tok;
|
||||
}
|
||||
|
||||
// Make a character constant token.
|
||||
static Token
|
||||
make_character_token(mpz_t val, Location location)
|
||||
{
|
||||
Token tok(TOKEN_CHARACTER, location);
|
||||
mpz_init(tok.u_.integer_value);
|
||||
mpz_swap(tok.u_.integer_value, val);
|
||||
return tok;
|
||||
}
|
||||
|
||||
// Make an integer token.
|
||||
static Token
|
||||
make_integer_token(mpz_t val, Location location)
|
||||
@ -225,6 +237,14 @@ class Token
|
||||
return *this->u_.string_value;
|
||||
}
|
||||
|
||||
// Return the value of a character constant.
|
||||
const mpz_t*
|
||||
character_value() const
|
||||
{
|
||||
go_assert(this->classification_ == TOKEN_CHARACTER);
|
||||
return &this->u_.integer_value;
|
||||
}
|
||||
|
||||
// Return the value of an integer.
|
||||
const mpz_t*
|
||||
integer_value() const
|
||||
@ -300,7 +320,7 @@ class Token
|
||||
} identifier_value;
|
||||
// The string value for TOKEN_STRING.
|
||||
std::string* string_value;
|
||||
// The token value for TOKEN_INTEGER.
|
||||
// The token value for TOKEN_CHARACTER or TOKEN_INTEGER.
|
||||
mpz_t integer_value;
|
||||
// The token value for TOKEN_FLOAT or TOKEN_IMAGINARY.
|
||||
mpfr_t float_value;
|
||||
|
@ -2391,6 +2391,12 @@ Parse::operand(bool may_be_sink)
|
||||
this->advance_token();
|
||||
return ret;
|
||||
|
||||
case Token::TOKEN_CHARACTER:
|
||||
ret = Expression::make_character(token->character_value(), NULL,
|
||||
token->location());
|
||||
this->advance_token();
|
||||
return ret;
|
||||
|
||||
case Token::TOKEN_INTEGER:
|
||||
ret = Expression::make_integer(token->integer_value(), NULL,
|
||||
token->location());
|
||||
@ -3168,6 +3174,7 @@ Parse::expression_may_start_here()
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case Token::TOKEN_CHARACTER:
|
||||
case Token::TOKEN_INTEGER:
|
||||
case Token::TOKEN_FLOAT:
|
||||
case Token::TOKEN_IMAGINARY:
|
||||
@ -3330,6 +3337,7 @@ Parse::statement(Label* label)
|
||||
break;
|
||||
|
||||
case Token::TOKEN_STRING:
|
||||
case Token::TOKEN_CHARACTER:
|
||||
case Token::TOKEN_INTEGER:
|
||||
case Token::TOKEN_FLOAT:
|
||||
case Token::TOKEN_IMAGINARY:
|
||||
@ -3389,6 +3397,7 @@ Parse::statement_may_start_here()
|
||||
return this->expression_may_start_here();
|
||||
|
||||
case Token::TOKEN_STRING:
|
||||
case Token::TOKEN_CHARACTER:
|
||||
case Token::TOKEN_INTEGER:
|
||||
case Token::TOKEN_FLOAT:
|
||||
case Token::TOKEN_IMAGINARY:
|
||||
|
@ -38,6 +38,8 @@ enum Runtime_function_type
|
||||
RFT_UINT64,
|
||||
// Go type uintptr, C type uintptr_t.
|
||||
RFT_UINTPTR,
|
||||
// Go type rune, C type int32_t.
|
||||
RFT_RUNE,
|
||||
// Go type float64, C type double.
|
||||
RFT_FLOAT64,
|
||||
// Go type complex128, C type __complex double.
|
||||
@ -108,6 +110,10 @@ runtime_function_type(Runtime_function_type bft)
|
||||
t = Type::lookup_integer_type("uint64");
|
||||
break;
|
||||
|
||||
case RFT_RUNE:
|
||||
t = Type::lookup_integer_type("int32");
|
||||
break;
|
||||
|
||||
case RFT_UINTPTR:
|
||||
t = Type::lookup_integer_type("uintptr");
|
||||
break;
|
||||
@ -203,6 +209,7 @@ convert_to_runtime_function_type(Runtime_function_type bft, Expression* e,
|
||||
case RFT_INT64:
|
||||
case RFT_UINT64:
|
||||
case RFT_UINTPTR:
|
||||
case RFT_RUNE:
|
||||
case RFT_FLOAT64:
|
||||
case RFT_COMPLEX128:
|
||||
case RFT_STRING:
|
||||
|
@ -36,7 +36,7 @@ DEF_GO_RUNTIME(STRINGITER, "runtime.stringiter", P2(STRING, INT), R1(INT))
|
||||
|
||||
// Range over a string, returning the next index and character.
|
||||
DEF_GO_RUNTIME(STRINGITER2, "runtime.stringiter2", P2(STRING, INT),
|
||||
R2(INT, INT))
|
||||
R2(INT, RUNE))
|
||||
|
||||
// Concatenate two strings.
|
||||
DEF_GO_RUNTIME(STRING_PLUS, "__go_string_plus", P2(STRING, STRING), R1(STRING))
|
||||
|
@ -5194,7 +5194,7 @@ For_range_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
|
||||
else if (range_type->is_string_type())
|
||||
{
|
||||
index_type = Type::lookup_integer_type("int");
|
||||
value_type = index_type;
|
||||
value_type = Type::lookup_integer_type("int32");
|
||||
}
|
||||
else if (range_type->map_type() != NULL)
|
||||
{
|
||||
|
@ -192,7 +192,10 @@ Type::make_non_abstract_type()
|
||||
switch (this->classification())
|
||||
{
|
||||
case TYPE_INTEGER:
|
||||
return Type::lookup_integer_type("int");
|
||||
if (this->integer_type()->is_rune())
|
||||
return Type::lookup_integer_type("int32");
|
||||
else
|
||||
return Type::lookup_integer_type("int");
|
||||
case TYPE_FLOAT:
|
||||
return Type::lookup_float_type("float64");
|
||||
case TYPE_COMPLEX:
|
||||
@ -320,6 +323,12 @@ Type::are_identical(const Type* t1, const Type* t2, bool errors_are_identical,
|
||||
t1 = t1->forwarded();
|
||||
t2 = t2->forwarded();
|
||||
|
||||
// Ignore aliases for purposes of type identity.
|
||||
if (t1->named_type() != NULL && t1->named_type()->is_alias())
|
||||
t1 = t1->named_type()->real_type();
|
||||
if (t2->named_type() != NULL && t2->named_type()->is_alias())
|
||||
t2 = t2->named_type()->real_type();
|
||||
|
||||
if (t1 == t2)
|
||||
return true;
|
||||
|
||||
@ -963,6 +972,8 @@ tree
|
||||
Type::type_descriptor_pointer(Gogo* gogo, Location location)
|
||||
{
|
||||
Type* t = this->forwarded();
|
||||
if (t->named_type() != NULL && t->named_type()->is_alias())
|
||||
t = t->named_type()->real_type();
|
||||
if (t->type_descriptor_var_ == NULL)
|
||||
{
|
||||
t->make_type_descriptor_var(gogo);
|
||||
@ -2317,6 +2328,21 @@ Integer_type::create_abstract_integer_type()
|
||||
return abstract_type;
|
||||
}
|
||||
|
||||
// Create a new abstract character type.
|
||||
|
||||
Integer_type*
|
||||
Integer_type::create_abstract_character_type()
|
||||
{
|
||||
static Integer_type* abstract_type;
|
||||
if (abstract_type == NULL)
|
||||
{
|
||||
abstract_type = new Integer_type(true, false, 32,
|
||||
RUNTIME_TYPE_KIND_INT32);
|
||||
abstract_type->set_is_rune();
|
||||
}
|
||||
return abstract_type;
|
||||
}
|
||||
|
||||
// Integer type compatibility.
|
||||
|
||||
bool
|
||||
@ -2399,6 +2425,14 @@ Type::make_abstract_integer_type()
|
||||
return Integer_type::create_abstract_integer_type();
|
||||
}
|
||||
|
||||
// Make an abstract character type.
|
||||
|
||||
Integer_type*
|
||||
Type::make_abstract_character_type()
|
||||
{
|
||||
return Integer_type::create_abstract_character_type();
|
||||
}
|
||||
|
||||
// Look up an integer type.
|
||||
|
||||
Named_type*
|
||||
@ -7215,6 +7249,18 @@ Named_type::message_name() const
|
||||
return this->named_object_->message_name();
|
||||
}
|
||||
|
||||
// Whether this is an alias. There are currently only two aliases so
|
||||
// we just recognize them by name.
|
||||
|
||||
bool
|
||||
Named_type::is_alias() const
|
||||
{
|
||||
if (!this->is_builtin())
|
||||
return false;
|
||||
const std::string& name(this->name());
|
||||
return name == "byte" || name == "rune";
|
||||
}
|
||||
|
||||
// Return the base type for this type. We have to be careful about
|
||||
// circular type definitions, which are invalid but may be seen here.
|
||||
|
||||
@ -7615,6 +7661,9 @@ Named_type::do_compare_is_identity(Gogo* gogo) const
|
||||
unsigned int
|
||||
Named_type::do_hash_for_method(Gogo* gogo) const
|
||||
{
|
||||
if (this->is_alias())
|
||||
return this->type_->named_type()->do_hash_for_method(gogo);
|
||||
|
||||
const std::string& name(this->named_object()->name());
|
||||
unsigned int ret = Type::hash_string(name, 0);
|
||||
|
||||
@ -7959,6 +8008,9 @@ Named_type::do_get_backend(Gogo* gogo)
|
||||
Expression*
|
||||
Named_type::do_type_descriptor(Gogo* gogo, Named_type* name)
|
||||
{
|
||||
if (name == NULL && this->is_alias())
|
||||
return this->type_->type_descriptor(gogo, this->type_);
|
||||
|
||||
// If NAME is not NULL, then we don't really want the type
|
||||
// descriptor for this type; we want the descriptor for the
|
||||
// underlying type, giving it the name NAME.
|
||||
@ -7973,7 +8025,12 @@ Named_type::do_type_descriptor(Gogo* gogo, Named_type* name)
|
||||
void
|
||||
Named_type::do_reflection(Gogo* gogo, std::string* ret) const
|
||||
{
|
||||
if (!Linemap::is_predeclared_location(this->location()))
|
||||
if (this->is_alias())
|
||||
{
|
||||
this->append_reflection(this->type_, gogo, ret);
|
||||
return;
|
||||
}
|
||||
if (!this->is_builtin())
|
||||
{
|
||||
const Package* package = this->named_object_->package();
|
||||
if (package != NULL)
|
||||
@ -7995,9 +8052,14 @@ Named_type::do_reflection(Gogo* gogo, std::string* ret) const
|
||||
void
|
||||
Named_type::do_mangled_name(Gogo* gogo, std::string* ret) const
|
||||
{
|
||||
if (this->is_alias())
|
||||
{
|
||||
this->append_mangled_name(this->type_, gogo, ret);
|
||||
return;
|
||||
}
|
||||
Named_object* no = this->named_object_;
|
||||
std::string name;
|
||||
if (Linemap::is_predeclared_location(this->location()))
|
||||
if (this->is_builtin())
|
||||
go_assert(this->in_function_ == NULL);
|
||||
else
|
||||
{
|
||||
|
@ -401,6 +401,10 @@ class Type
|
||||
static Integer_type*
|
||||
make_abstract_integer_type();
|
||||
|
||||
// Make an abstract type for a character constant.
|
||||
static Integer_type*
|
||||
make_abstract_character_type();
|
||||
|
||||
// Make a named integer type with a specified size.
|
||||
// RUNTIME_TYPE_KIND is the code to use in reflection information,
|
||||
// to distinguish int and int32.
|
||||
@ -1374,6 +1378,10 @@ class Integer_type : public Type
|
||||
static Integer_type*
|
||||
create_abstract_integer_type();
|
||||
|
||||
// Create an abstract character type.
|
||||
static Integer_type*
|
||||
create_abstract_character_type();
|
||||
|
||||
// Whether this is an abstract integer type.
|
||||
bool
|
||||
is_abstract() const
|
||||
@ -2674,6 +2682,11 @@ class Named_type : public Type
|
||||
is_builtin() const
|
||||
{ return Linemap::is_predeclared_location(this->location_); }
|
||||
|
||||
// Whether this is an alias. There are currently two aliases: byte
|
||||
// and rune.
|
||||
bool
|
||||
is_alias() const;
|
||||
|
||||
// Whether this is a circular type: a pointer or function type that
|
||||
// refers to itself, which is not possible in C.
|
||||
bool
|
||||
|
@ -7,18 +7,18 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
nchar := 0;
|
||||
a := []int { '日', '本', '語', 0xFFFD };
|
||||
nchar := 0
|
||||
a := []rune{'日', '本', '語', 0xFFFD}
|
||||
for _, char := range "日本語\xc0" {
|
||||
if nchar >= len(a) {
|
||||
println("BUG");
|
||||
break;
|
||||
println("BUG")
|
||||
break
|
||||
}
|
||||
if char != a[nchar] {
|
||||
println("expected", a[nchar], "got", char);
|
||||
println("BUG");
|
||||
break;
|
||||
println("expected", a[nchar], "got", char)
|
||||
println("BUG")
|
||||
break
|
||||
}
|
||||
nchar++;
|
||||
nchar++
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ func main() {
|
||||
}
|
||||
|
||||
/* create string with int array */
|
||||
var z2 [3]int
|
||||
var z2 [3]rune
|
||||
z2[0] = 'a'
|
||||
z2[1] = '\u1234'
|
||||
z2[2] = 'c'
|
||||
|
@ -172,7 +172,7 @@ func makestring() string {
|
||||
}
|
||||
|
||||
func teststring() {
|
||||
s := 0
|
||||
var s rune
|
||||
nmake = 0
|
||||
for _, v := range makestring() {
|
||||
s += v
|
||||
@ -208,7 +208,7 @@ func teststring1() {
|
||||
|
||||
func makemap() map[int]int {
|
||||
nmake++
|
||||
return map[int]int{0:'a', 1:'b', 2:'c', 3:'d', 4:'☺'}
|
||||
return map[int]int{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: '☺'}
|
||||
}
|
||||
|
||||
func testmap() {
|
||||
|
@ -14,7 +14,7 @@ const N = 11 + 1 // length of a board row (+1 for newline)
|
||||
// The board must be surrounded by 2 illegal fields in each direction
|
||||
// so that move() doesn't need to check the board boundaries. Periods
|
||||
// represent illegal fields, ● are pegs, and ○ are holes.
|
||||
var board = []int(
|
||||
var board = []rune(
|
||||
`...........
|
||||
...........
|
||||
....●●●....
|
||||
@ -28,7 +28,6 @@ var board = []int(
|
||||
...........
|
||||
`)
|
||||
|
||||
|
||||
// center is the position of the center hole if there is a single one;
|
||||
// otherwise it is -1.
|
||||
var center int
|
||||
@ -46,7 +45,6 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var moves int // number of times move is called
|
||||
|
||||
// move tests if there is a peg at position pos that can jump over another peg
|
||||
@ -63,7 +61,6 @@ func move(pos, dir int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
// unmove reverts a previously executed valid move.
|
||||
func unmove(pos, dir int) {
|
||||
board[pos] = '●'
|
||||
@ -71,7 +68,6 @@ func unmove(pos, dir int) {
|
||||
board[pos+2*dir] = '○'
|
||||
}
|
||||
|
||||
|
||||
// solve tries to find a sequence of moves such that there is only one peg left
|
||||
// at the end; if center is >= 0, that last peg must be in the center position.
|
||||
// If a solution is found, solve prints the board after each move in a backward
|
||||
@ -110,7 +106,6 @@ func solve() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
func main() {
|
||||
if !solve() {
|
||||
println("no solution found")
|
||||
|
@ -35,14 +35,14 @@ func assert(a, b, c string) {
|
||||
}
|
||||
|
||||
const (
|
||||
gx1 = "aä本☺"
|
||||
gx2 = "aä\xFF\xFF本☺"
|
||||
gx1 = "aä本☺"
|
||||
gx2 = "aä\xFF\xFF本☺"
|
||||
gx2fix = "aä\uFFFD\uFFFD本☺"
|
||||
)
|
||||
|
||||
var (
|
||||
gr1 = []int(gx1)
|
||||
gr2 = []int(gx2)
|
||||
gr1 = []rune(gx1)
|
||||
gr2 = []rune(gx2)
|
||||
gb1 = []byte(gx1)
|
||||
gb2 = []byte(gx2)
|
||||
)
|
||||
@ -93,26 +93,26 @@ func main() {
|
||||
|
||||
// test large runes. perhaps not the most logical place for this test.
|
||||
var r int32
|
||||
r = 0x10ffff; // largest rune value
|
||||
r = 0x10ffff // largest rune value
|
||||
s = string(r)
|
||||
assert(s, "\xf4\x8f\xbf\xbf", "largest rune")
|
||||
r = 0x10ffff + 1
|
||||
s = string(r)
|
||||
assert(s, "\xef\xbf\xbd", "too-large rune")
|
||||
|
||||
assert(string(gr1), gx1, "global ->[]int")
|
||||
assert(string(gr2), gx2fix, "global invalid ->[]int")
|
||||
assert(string(gr1), gx1, "global ->[]rune")
|
||||
assert(string(gr2), gx2fix, "global invalid ->[]rune")
|
||||
assert(string(gb1), gx1, "->[]byte")
|
||||
assert(string(gb2), gx2, "global invalid ->[]byte")
|
||||
|
||||
var (
|
||||
r1 = []int(gx1)
|
||||
r2 = []int(gx2)
|
||||
r1 = []rune(gx1)
|
||||
r2 = []rune(gx2)
|
||||
b1 = []byte(gx1)
|
||||
b2 = []byte(gx2)
|
||||
)
|
||||
assert(string(r1), gx1, "->[]int")
|
||||
assert(string(r2), gx2fix, "invalid ->[]int")
|
||||
assert(string(r1), gx1, "->[]rune")
|
||||
assert(string(r2), gx2fix, "invalid ->[]rune")
|
||||
assert(string(b1), gx1, "->[]byte")
|
||||
assert(string(b2), gx2, "invalid ->[]byte")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user