gofrontend\go\statements.cc
根据range_type,进行不同的处理。
slice、array、string、map、channel
// Arrange to do a loop appropriate for the type. We will produce
// for INIT ; COND ; POST {
// ITER_INIT
// INDEX = INDEX_TEMP
// VALUE = VALUE_TEMP // If there is a value
// original statements
// }
if (range_type->is_slice_type())
this->lower_range_slice(gogo, temp_block, body, range_object, range_temp,
index_temp, value_temp, &init, &cond, &iter_init,
&post);
else if (range_type->array_type() != NULL)
this->lower_range_array(gogo, temp_block, body, range_object, range_temp,
index_temp, value_temp, &init, &cond, &iter_init,
&post);
else if (range_type->is_string_type())
this->lower_range_string(gogo, temp_block, body, range_object, range_temp,
index_temp, value_temp, &init, &cond, &iter_init,
&post);
else if (range_type->map_type() != NULL)
this->lower_range_map(gogo, range_type->map_type(), temp_block, body,
range_object, range_temp, index_temp, value_temp,
&init, &cond, &iter_init, &post);
else if (range_type->channel_type() != NULL)
this->lower_range_channel(gogo, temp_block, body, range_object, range_temp,
index_temp, value_temp, &init, &cond, &iter_init,
&post);
else
go_unreachable();
slice
// Lower a for range over a slice.
// The loop we generate:
// for_temp := range
// len_temp := len(for_temp)
// for index_temp = 0; index_temp < len_temp; index_temp++ {
// value_temp = for_temp[index_temp]
// index = index_temp
// value = value_temp
// original body
// }
//
// Using for_temp means that we don't need to check bounds when
// fetching range_temp[index_temp].
array
// Lower a for range over an array.
// The loop we generate:
// len_temp := len(range)
// range_temp := range
// for index_temp = 0; index_temp < len_temp; index_temp++ {
// value_temp = range_temp[index_temp]
// index = index_temp
// value = value_temp
// original body
// }
string
// Lower a for range over a string.
// The loop we generate:
// len_temp := len(range)
// var next_index_temp int
// for index_temp = 0; index_temp < len_temp; index_temp = next_index_temp {
// value_temp = rune(range[index_temp])
// if value_temp < utf8.RuneSelf {
// next_index_temp = index_temp + 1
// } else {
// value_temp, next_index_temp = decoderune(range, index_temp)
// }
// index = index_temp
// value = value_temp
// // original body
// }
map
// Lower a for range over a map.
// The runtime uses a struct to handle ranges over a map. The
// struct is built by Map_type::hiter_type for a specific map type.
// The loop we generate:
// var hiter map_iteration_struct
// for mapiterinit(type, range, &hiter); hiter.key != nil; mapiternext(&hiter) {
// index_temp = *hiter.key
// value_temp = *hiter.val
// index = index_temp
// value = value_temp
// original body
// }