reflect: add support for non-named basic types
Этот коммит содержится в:
		
							родитель
							
								
									222c4c75b1
								
							
						
					
					
						коммит
						fb23e9c212
					
				
					 7 изменённых файлов: 397 добавлений и 26 удалений
				
			
		|  | @ -104,15 +104,6 @@ func (t *typeInfo) getMethod(signature *signatureInfo) *methodInfo { | |||
| 	panic("could not find method") | ||||
| } | ||||
| 
 | ||||
| // id returns the fully-qualified type name including import path, removing the | ||||
| // $type suffix. | ||||
| func (t *typeInfo) id() string { | ||||
| 	if !strings.HasSuffix(t.name, "$type") { | ||||
| 		panic("concrete type does not have $type suffix: " + t.name) | ||||
| 	} | ||||
| 	return t.name[:len(t.name)-len("$type")] | ||||
| } | ||||
| 
 | ||||
| // typeInfoSlice implements sort.Slice, sorting the most commonly used types | ||||
| // first. | ||||
| type typeInfoSlice []*typeInfo | ||||
|  | @ -423,9 +414,7 @@ func (p *lowerInterfacesPass) run() { | |||
| 	} | ||||
| 
 | ||||
| 	// Assign a type code for each type. | ||||
| 	for i, t := range typeSlice { | ||||
| 		t.num = uint64(i + 1) | ||||
| 	} | ||||
| 	p.assignTypeCodes(typeSlice) | ||||
| 
 | ||||
| 	// Replace each call to runtime.makeInterface with the constant type code. | ||||
| 	for _, use := range makeInterfaceUses { | ||||
|  | @ -691,7 +680,7 @@ func (p *lowerInterfacesPass) createInterfaceMethodFunc(itf *interfaceInfo, sign | |||
| 
 | ||||
| 	// Define all possible functions that can be called. | ||||
| 	for _, typ := range itf.types { | ||||
| 		bb := llvm.AddBasicBlock(fn, typ.id()) | ||||
| 		bb := llvm.AddBasicBlock(fn, typ.name) | ||||
| 		sw.AddCase(llvm.ConstInt(p.uintptrType, typ.num, false), bb) | ||||
| 
 | ||||
| 		// The function we will redirect to when the interface has this type. | ||||
|  |  | |||
|  | @ -79,9 +79,58 @@ func (c *Compiler) parseMakeInterface(val llvm.Value, typ types.Type, global str | |||
| // It returns a pointer to an external global which should be replaced with the | ||||
| // real type in the interface lowering pass. | ||||
| func (c *Compiler) getTypeCode(typ types.Type) llvm.Value { | ||||
| 	global := c.mod.NamedGlobal(typ.String() + "$type") | ||||
| 	var globalName string | ||||
| 	switch typ := typ.(type) { | ||||
| 	case *types.Basic: | ||||
| 		var name string | ||||
| 		switch typ.Kind() { | ||||
| 		case types.Bool: | ||||
| 			name = "bool" | ||||
| 		case types.Int: | ||||
| 			name = "int" | ||||
| 		case types.Int8: | ||||
| 			name = "int8" | ||||
| 		case types.Int16: | ||||
| 			name = "int16" | ||||
| 		case types.Int32: | ||||
| 			name = "int32" | ||||
| 		case types.Int64: | ||||
| 			name = "int64" | ||||
| 		case types.Uint: | ||||
| 			name = "uint" | ||||
| 		case types.Uint8: | ||||
| 			name = "uint8" | ||||
| 		case types.Uint16: | ||||
| 			name = "uint16" | ||||
| 		case types.Uint32: | ||||
| 			name = "uint32" | ||||
| 		case types.Uint64: | ||||
| 			name = "uint64" | ||||
| 		case types.Uintptr: | ||||
| 			name = "uintptr" | ||||
| 		case types.Float32: | ||||
| 			name = "float32" | ||||
| 		case types.Float64: | ||||
| 			name = "float64" | ||||
| 		case types.Complex64: | ||||
| 			name = "complex64" | ||||
| 		case types.Complex128: | ||||
| 			name = "complex128" | ||||
| 		case types.String: | ||||
| 			name = "string" | ||||
| 		case types.UnsafePointer: | ||||
| 			name = "unsafeptr" | ||||
| 		default: | ||||
| 			panic("unknown basic type: " + typ.Name()) | ||||
| 		} | ||||
| 		globalName = "type:basic:" + name | ||||
| 	default: | ||||
| 		// Unknown type, fall back to the .String() method for identification. | ||||
| 		globalName = "type:other:" + typ.String() | ||||
| 	} | ||||
| 	global := c.mod.NamedGlobal(globalName) | ||||
| 	if global.IsNil() { | ||||
| 		global = llvm.AddGlobal(c.mod, c.ctx.Int8Type(), typ.String()+"$type") | ||||
| 		global = llvm.AddGlobal(c.mod, c.ctx.Int8Type(), globalName) | ||||
| 		global.SetGlobalConstant(true) | ||||
| 	} | ||||
| 	return global | ||||
|  |  | |||
							
								
								
									
										55
									
								
								compiler/reflect.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										55
									
								
								compiler/reflect.go
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -0,0 +1,55 @@ | |||
| package compiler | ||||
| 
 | ||||
| import ( | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| var basicTypes = map[string]uint64{ | ||||
| 	"bool":       1, | ||||
| 	"int":        2, | ||||
| 	"int8":       3, | ||||
| 	"int16":      4, | ||||
| 	"int32":      5, | ||||
| 	"int64":      6, | ||||
| 	"uint":       7, | ||||
| 	"uint8":      8, | ||||
| 	"uint16":     9, | ||||
| 	"uint32":     10, | ||||
| 	"uint64":     11, | ||||
| 	"uintptr":    12, | ||||
| 	"float32":    13, | ||||
| 	"float64":    14, | ||||
| 	"complex64":  15, | ||||
| 	"complex128": 16, | ||||
| 	"string":     17, | ||||
| 	"unsafeptr":  18, | ||||
| } | ||||
| 
 | ||||
| func (c *Compiler) assignTypeCodes(typeSlice typeInfoSlice) { | ||||
| 	fn := c.mod.NamedFunction("reflect.ValueOf") | ||||
| 	if fn.IsNil() { | ||||
| 		// reflect.ValueOf is never used, so we can use the most efficient | ||||
| 		// encoding possible. | ||||
| 		for i, t := range typeSlice { | ||||
| 			t.num = uint64(i + 1) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// Assign typecodes the way the reflect package expects. | ||||
| 	fallbackIndex := 1 | ||||
| 	for _, t := range typeSlice { | ||||
| 		if strings.HasPrefix(t.name, "type:basic:") { | ||||
| 			// Basic types have a typecode with the lowest bit set to 0. | ||||
| 			num, ok := basicTypes[t.name[len("type:basic:"):]] | ||||
| 			if !ok { | ||||
| 				panic("invalid basic type: " + t.name) | ||||
| 			} | ||||
| 			t.num = num<<1 | 0 | ||||
| 		} else { | ||||
| 			// Fallback types have a typecode with the lowest bit set to 1. | ||||
| 			t.num = uint64(fallbackIndex<<1 | 1) | ||||
| 			fallbackIndex++ | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -26,6 +26,8 @@ const ( | |||
| 	Float64 | ||||
| 	Complex64 | ||||
| 	Complex128 | ||||
| 	String | ||||
| 	UnsafePointer | ||||
| 	Array | ||||
| 	Chan | ||||
| 	Func | ||||
|  | @ -33,11 +35,52 @@ const ( | |||
| 	Map | ||||
| 	Ptr | ||||
| 	Slice | ||||
| 	String | ||||
| 	Struct | ||||
| 	UnsafePointer | ||||
| ) | ||||
| 
 | ||||
| func (k Kind) String() string { | ||||
| 	switch k { | ||||
| 	case Bool: | ||||
| 		return "bool" | ||||
| 	case Int: | ||||
| 		return "int" | ||||
| 	case Int8: | ||||
| 		return "int8" | ||||
| 	case Int16: | ||||
| 		return "int16" | ||||
| 	case Int32: | ||||
| 		return "int32" | ||||
| 	case Int64: | ||||
| 		return "int64" | ||||
| 	case Uint: | ||||
| 		return "uint" | ||||
| 	case Uint8: | ||||
| 		return "uint8" | ||||
| 	case Uint16: | ||||
| 		return "uint16" | ||||
| 	case Uint32: | ||||
| 		return "uint32" | ||||
| 	case Uint64: | ||||
| 		return "uint64" | ||||
| 	case Uintptr: | ||||
| 		return "uintptr" | ||||
| 	case Float32: | ||||
| 		return "float32" | ||||
| 	case Float64: | ||||
| 		return "float64" | ||||
| 	case Complex64: | ||||
| 		return "complex64" | ||||
| 	case Complex128: | ||||
| 		return "complex128" | ||||
| 	case String: | ||||
| 		return "string" | ||||
| 	case UnsafePointer: | ||||
| 		return "unsafe.Pointer" | ||||
| 	default: | ||||
| 		return "T" | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // The typecode as used in an interface{}. | ||||
| type Type uintptr | ||||
| 
 | ||||
|  | @ -50,8 +93,13 @@ func (t Type) String() string { | |||
| } | ||||
| 
 | ||||
| func (t Type) Kind() Kind { | ||||
| 	if t & 1 == 0 { | ||||
| 		// Basic type | ||||
| 		return Kind(t >> 1) | ||||
| 	} else { | ||||
| 		return Invalid // TODO | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (t Type) Elem() Type { | ||||
| 	panic("unimplemented: (reflect.Type).Elem()") | ||||
|  |  | |||
|  | @ -33,7 +33,14 @@ func (v Value) IsNil() bool { | |||
| } | ||||
| 
 | ||||
| func (v Value) Pointer() uintptr { | ||||
| 	switch v.Type().Kind() { | ||||
| 	case UnsafePointer: | ||||
| 		return uintptr(v.value) | ||||
| 	case Chan, Func, Map, Ptr, Slice: | ||||
| 		panic("unimplemented: (reflect.Value).Pointer()") | ||||
| 	default: | ||||
| 		panic(&ValueError{"Pointer"}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (v Value) IsValid() bool { | ||||
|  | @ -57,27 +64,132 @@ func (v Value) CanSet() bool { | |||
| } | ||||
| 
 | ||||
| func (v Value) Bool() bool { | ||||
| 	panic("unimplemented: (reflect.Value).Bool()") | ||||
| 	switch v.Type().Kind() { | ||||
| 	case Bool: | ||||
| 		return uintptr(v.value) != 0 | ||||
| 	default: | ||||
| 		panic(&ValueError{"Bool"}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (v Value) Int() int64 { | ||||
| 	panic("unimplemented: (reflect.Value).Int()") | ||||
| 	switch v.Type().Kind() { | ||||
| 	case Int: | ||||
| 		if unsafe.Sizeof(int(0)) <= unsafe.Sizeof(uintptr(0)) { | ||||
| 			return int64(int(uintptr(v.value))) | ||||
| 		} else { | ||||
| 			return int64(*(*int)(v.value)) | ||||
| 		} | ||||
| 	case Int8: | ||||
| 		return int64(int8(uintptr(v.value))) | ||||
| 	case Int16: | ||||
| 		return int64(int16(uintptr(v.value))) | ||||
| 	case Int32: | ||||
| 		if unsafe.Sizeof(int32(0)) <= unsafe.Sizeof(uintptr(0)) { | ||||
| 			return int64(int32(uintptr(v.value))) | ||||
| 		} else { | ||||
| 			return int64(*(*int32)(v.value)) | ||||
| 		} | ||||
| 		return int64(uintptr(v.value)) | ||||
| 	case Int64: | ||||
| 		if unsafe.Sizeof(int64(0)) <= unsafe.Sizeof(uintptr(0)) { | ||||
| 			return int64(uintptr(v.value)) | ||||
| 		} else { | ||||
| 			return *(*int64)(v.value) | ||||
| 		} | ||||
| 	default: | ||||
| 		panic(&ValueError{"Int"}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (v Value) Uint() uint64 { | ||||
| 	panic("unimplemented: (reflect.Value).Uint()") | ||||
| 	switch v.Type().Kind() { | ||||
| 	case Uintptr, Uint8, Uint16: | ||||
| 		return uint64(uintptr(v.value)) | ||||
| 	case Uint: | ||||
| 		if unsafe.Sizeof(uint(0)) <= unsafe.Sizeof(uintptr(0)) { | ||||
| 			return uint64(uintptr(v.value)) | ||||
| 		} else { | ||||
| 			// For systems with 16-bit pointers. | ||||
| 			return uint64(*(*uint)(v.value)) | ||||
| 		} | ||||
| 	case Uint32: | ||||
| 		if unsafe.Sizeof(uint32(0)) <= unsafe.Sizeof(uintptr(0)) { | ||||
| 			return uint64(uintptr(v.value)) | ||||
| 		} else { | ||||
| 			// For systems with 16-bit pointers. | ||||
| 			return uint64(*(*uint32)(v.value)) | ||||
| 		} | ||||
| 	case Uint64: | ||||
| 		if unsafe.Sizeof(uint64(0)) <= unsafe.Sizeof(uintptr(0)) { | ||||
| 			return uint64(uintptr(v.value)) | ||||
| 		} else { | ||||
| 			// For systems with 16-bit or 32-bit pointers. | ||||
| 			return *(*uint64)(v.value) | ||||
| 		} | ||||
| 	default: | ||||
| 		panic(&ValueError{"Uint"}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (v Value) Float() float64 { | ||||
| 	panic("unimplemented: (reflect.Value).Float()") | ||||
| 	switch v.Type().Kind() { | ||||
| 	case Float32: | ||||
| 		if unsafe.Sizeof(float32(0)) <= unsafe.Sizeof(uintptr(0)) { | ||||
| 			// The float is directly stored in the interface value on systems | ||||
| 			// with 32-bit and 64-bit pointers. | ||||
| 			return float64(*(*float32)(unsafe.Pointer(&v.value))) | ||||
| 		} else { | ||||
| 			// The float is stored as an external value on systems with 16-bit | ||||
| 			// pointers. | ||||
| 			return float64(*(*float32)(v.value)) | ||||
| 		} | ||||
| 	case Float64: | ||||
| 		if unsafe.Sizeof(float64(0)) <= unsafe.Sizeof(uintptr(0)) { | ||||
| 			// The float is directly stored in the interface value on systems | ||||
| 			// with 64-bit pointers. | ||||
| 			return *(*float64)(unsafe.Pointer(&v.value)) | ||||
| 		} else { | ||||
| 			// For systems with 16-bit and 32-bit pointers. | ||||
| 			return *(*float64)(v.value) | ||||
| 		} | ||||
| 	default: | ||||
| 		panic(&ValueError{"Float"}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (v Value) Complex() complex128 { | ||||
| 	panic("unimplemented: (reflect.Value).Complex()") | ||||
| 	switch v.Type().Kind() { | ||||
| 	case Complex64: | ||||
| 		if unsafe.Sizeof(complex64(0)) <= unsafe.Sizeof(uintptr(0)) { | ||||
| 			// The complex number is directly stored in the interface value on | ||||
| 			// systems with 64-bit pointers. | ||||
| 			return complex128(*(*complex64)(unsafe.Pointer(&v.value))) | ||||
| 		} else { | ||||
| 			// The complex number is stored as an external value on systems with | ||||
| 			// 16-bit and 32-bit pointers. | ||||
| 			return complex128(*(*complex64)(v.value)) | ||||
| 		} | ||||
| 	case Complex128: | ||||
| 		// This is a 128-bit value, which is always stored as an external value. | ||||
| 		// It may be stored in the pointer directly on very uncommon | ||||
| 		// architectures with 128-bit pointers, however. | ||||
| 		return *(*complex128)(v.value) | ||||
| 	default: | ||||
| 		panic(&ValueError{"Complex"}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (v Value) String() string { | ||||
| 	panic("unimplemented: (reflect.Value).String()") | ||||
| 	switch v.Type().Kind() { | ||||
| 	case String: | ||||
| 		// A string value is always bigger than a pointer as it is made of a | ||||
| 		// pointer and a length. | ||||
| 		return *(*string)(v.value) | ||||
| 	default: | ||||
| 		// Special case because of the special treatment of .String() in Go. | ||||
| 		return "<T>" | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (v Value) Bytes() []byte { | ||||
|  | @ -147,3 +259,11 @@ func (v Value) SetString(x string) { | |||
| func MakeSlice(typ Type, len, cap int) Value { | ||||
| 	panic("unimplemented: reflect.MakeSlice()") | ||||
| } | ||||
| 
 | ||||
| type ValueError struct { | ||||
| 	Method string | ||||
| } | ||||
| 
 | ||||
| func (e *ValueError) Error() string { | ||||
| 	return "reflect: call of reflect.Value." + e.Method + " on invalid type" | ||||
| } | ||||
|  |  | |||
							
								
								
									
										62
									
								
								testdata/reflect.go
									
										
									
									
										предоставленный
									
									
								
							
							
						
						
									
										62
									
								
								testdata/reflect.go
									
										
									
									
										предоставленный
									
									
								
							|  | @ -1,6 +1,9 @@ | |||
| package main | ||||
| 
 | ||||
| import "reflect" | ||||
| import ( | ||||
| 	"reflect" | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| type myint int | ||||
| 
 | ||||
|  | @ -9,4 +12,61 @@ func main() { | |||
| 	println(reflect.TypeOf(int(3)) == reflect.TypeOf(int(5))) | ||||
| 	println(reflect.TypeOf(int(3)) == reflect.TypeOf(uint(5))) | ||||
| 	println(reflect.TypeOf(myint(3)) == reflect.TypeOf(int(5))) | ||||
| 
 | ||||
| 	println("\nvalues of interfaces") | ||||
| 	for _, v := range []interface{}{ | ||||
| 		true, | ||||
| 		false, | ||||
| 		int(2000), | ||||
| 		int(-2000), | ||||
| 		uint(2000), | ||||
| 		int8(-3), | ||||
| 		int8(3), | ||||
| 		uint8(200), | ||||
| 		int16(-300), | ||||
| 		int16(300), | ||||
| 		uint16(50000), | ||||
| 		int32(7 << 20), | ||||
| 		int32(-7 << 20), | ||||
| 		uint32(7 << 20), | ||||
| 		int64(9 << 40), | ||||
| 		int64(-9 << 40), | ||||
| 		uint64(9 << 40), | ||||
| 		uintptr(12345), | ||||
| 		float32(3.14), | ||||
| 		float64(3.14), | ||||
| 		complex64(1.2 + 0.3i), | ||||
| 		complex128(1.3 + 0.4i), | ||||
| 		"foo", | ||||
| 		unsafe.Pointer(new(int)), | ||||
| 	} { | ||||
| 		showValue(v) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func showValue(v interface{}) { | ||||
| 	rv := reflect.ValueOf(v) | ||||
| 	rt := rv.Type() | ||||
| 	if reflect.TypeOf(v) != rt { | ||||
| 		panic("direct TypeOf() is different from ValueOf().Type()") | ||||
| 	} | ||||
| 	println("reflect type:", rt.Kind().String()) | ||||
| 	switch rt.Kind() { | ||||
| 	case reflect.Bool: | ||||
| 		println("  bool:", rv.Bool()) | ||||
| 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||||
| 		println("  int:", rv.Int()) | ||||
| 	case reflect.Uint, reflect.Uintptr, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||||
| 		println("  uint:", rv.Uint()) | ||||
| 	case reflect.Float32, reflect.Float64: | ||||
| 		println("  float:", rv.Float()) | ||||
| 	case reflect.Complex64, reflect.Complex128: | ||||
| 		println("  complex:", rv.Complex()) | ||||
| 	case reflect.String: | ||||
| 		println("  string:", rv.String()) | ||||
| 	case reflect.UnsafePointer: | ||||
| 		println("  pointer:", rv.Pointer() != 0) | ||||
| 	default: | ||||
| 		println("  unknown type kind!") | ||||
| 	} | ||||
| } | ||||
|  |  | |||
							
								
								
									
										50
									
								
								testdata/reflect.txt
									
										
									
									
										предоставленный
									
									
								
							
							
						
						
									
										50
									
								
								testdata/reflect.txt
									
										
									
									
										предоставленный
									
									
								
							|  | @ -2,3 +2,53 @@ matching types | |||
| true | ||||
| false | ||||
| false | ||||
| 
 | ||||
| values of interfaces | ||||
| reflect type: bool | ||||
|   bool: true | ||||
| reflect type: bool | ||||
|   bool: false | ||||
| reflect type: int | ||||
|   int: 2000 | ||||
| reflect type: int | ||||
|   int: -2000 | ||||
| reflect type: uint | ||||
|   uint: 2000 | ||||
| reflect type: int8 | ||||
|   int: -3 | ||||
| reflect type: int8 | ||||
|   int: 3 | ||||
| reflect type: uint8 | ||||
|   uint: 200 | ||||
| reflect type: int16 | ||||
|   int: -300 | ||||
| reflect type: int16 | ||||
|   int: 300 | ||||
| reflect type: uint16 | ||||
|   uint: 50000 | ||||
| reflect type: int32 | ||||
|   int: 7340032 | ||||
| reflect type: int32 | ||||
|   int: -7340032 | ||||
| reflect type: uint32 | ||||
|   uint: 7340032 | ||||
| reflect type: int64 | ||||
|   int: 9895604649984 | ||||
| reflect type: int64 | ||||
|   int: -9895604649984 | ||||
| reflect type: uint64 | ||||
|   uint: 9895604649984 | ||||
| reflect type: uintptr | ||||
|   uint: 12345 | ||||
| reflect type: float32 | ||||
|   float: +3.140000e+000 | ||||
| reflect type: float64 | ||||
|   float: +3.140000e+000 | ||||
| reflect type: complex64 | ||||
|   complex: (+1.200000e+000+3.000000e-001i) | ||||
| reflect type: complex128 | ||||
|   complex: (+1.300000e+000+4.000000e-001i) | ||||
| reflect type: string | ||||
|   string: foo | ||||
| reflect type: unsafe.Pointer | ||||
|   pointer: true | ||||
|  |  | |||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче
	
	 Ayke van Laethem
						Ayke van Laethem