diff --git a/usr/r/reflect/Makefile b/usr/r/reflect/Makefile index 1d999f4e0a..b0927a3b89 100644 --- a/usr/r/reflect/Makefile +++ b/usr/r/reflect/Makefile @@ -3,7 +3,8 @@ # license that can be found in the LICENSE file. # DO NOT EDIT. Automatically generated by gobuild. -# gobuild -m reflect tostring.go type.go value.go cast_amd64.s +# gobuild -m reflect tostring.go type.go value.go cast_amd64.s\ +# typestring.c O=6 GC=$(O)g CC=$(O)c -w @@ -33,6 +34,7 @@ clean: O1=\ type.$O\ cast_amd64.$O\ + typestring.$O\ O2=\ value.$O\ diff --git a/usr/r/reflect/main.go b/usr/r/reflect/main.go index 1967ed7c39..f0a2c021d4 100644 --- a/usr/r/reflect/main.go +++ b/usr/r/reflect/main.go @@ -34,19 +34,23 @@ func valuedump(s string) { case reflect.Uint64Kind: v.(reflect.Uint64Value).Put(64); case reflect.Float32Kind: - v.(reflect.Float32Value).Put(320.0); + v.(reflect.Float32Value).Put(32.0); case reflect.Float64Kind: - v.(reflect.Float32Value).Put(640.0); + v.(reflect.Float64Value).Put(64.0); case reflect.StringKind: v.(reflect.StringValue).Put("stringy cheese"); } print(s, " value = ", reflect.ValueToString(v), "\n"); } +export type empty interface {} + +export type T struct { a int; b float64 } + func main() { var s string; var t reflect.Type; - + typedump("int8"); typedump("int16"); typedump("int32"); @@ -82,5 +86,28 @@ func main() { valuedump("uint16"); valuedump("uint32"); valuedump("uint64"); + valuedump("float32"); + valuedump("float64"); valuedump("string"); + valuedump("*int8"); + valuedump("**int8"); + valuedump("[32]int32"); + valuedump("**P.integer"); + valuedump("[32]int32"); + valuedump("[]int8"); + valuedump("*map[string]int32"); + valuedump("*chan<-string"); + valuedump("struct {c *chan *int32; d float32}"); + valuedump("*(a int8, b int32)"); + valuedump("struct {c *(? *chan *P.integer, ? *int8)}"); + valuedump("struct {a int8; b int32}"); + valuedump("struct {a int8; b int8; b int32}"); + valuedump("struct {a int8; b int8; c int8; b int32}"); + valuedump("struct {a int8; b int8; c int8; d int8; b int32}"); + valuedump("struct {a int8; b int8; c int8; d int8; e int8; b int32}"); + + v := new(T); + a, b := sys.reflect(v.(empty)); + println(a, b); + typedump(b); } diff --git a/usr/r/reflect/tostring.go b/usr/r/reflect/tostring.go index 0449a6e9e0..17a0a79fc6 100644 --- a/usr/r/reflect/tostring.go +++ b/usr/r/reflect/tostring.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // Reflection library. -// Formatting of types for debugging. +// Formatting of types and values for debugging. package reflect @@ -15,13 +15,17 @@ import ( export func TypeToString(typ Type) string export func ValueToString(val Value) string -func TypeFieldsToString(t Type, sep string) string { - s := t.(StructType); +type HasFields interface { + Field(i int) (name string, typ Type, offset uint64); + Len() int; +} + +func TypeFieldsToString(t HasFields, sep string) string { var str string; - for i := 0; i < s.Len(); i++ { - str1, t := s.Field(i); - str1 += " " + TypeToString(t); - if i < s.Len() - 1 { + for i := 0; i < t.Len(); i++ { + str1, typ, offset := t.Field(i); + str1 += " " + TypeToString(typ); + if i < t.Len() - 1 { str1 += sep + " "; } str += str1; @@ -33,7 +37,7 @@ func TypeToString(typ Type) string { var str string; switch(typ.Kind()) { case MissingKind: - return "missing"; + return "$missing$"; case Int8Kind: return "int8"; case Int16Kind: @@ -63,10 +67,10 @@ func TypeToString(typ Type) string { return "*" + TypeToString(p.Sub()); case ArrayKind: a := typ.(ArrayType); - if a.Len() < 0 { + if a.Open() { str = "[]" } else { - str = "[" + strings.itoa(a.Len()) + "]" + str = "[" + strings.ltoa(int64(a.Len())) + "]" } return str + TypeToString(a.Elem()); case MapKind: @@ -92,8 +96,7 @@ func TypeToString(typ Type) string { return "interface{" + TypeFieldsToString(typ, ";") + "}"; case FuncKind: f := typ.(FuncType); - str = "func"; - str += "(" + TypeFieldsToString(f.In(), ",") + ")"; + str = "(" + TypeFieldsToString(f.In(), ",") + ")"; if f.Out() != nil { str += "(" + TypeFieldsToString(f.Out(), ",") + ")"; } @@ -106,7 +109,11 @@ func TypeToString(typ Type) string { // TODO: want an unsigned one too func integer(v int64) string { - return strings.itol(v); + return strings.ltoa(v); +} + +func floatingpoint(v float64) string { + return strings.dtoa(v); } func ValueToString(val Value) string { @@ -132,16 +139,56 @@ func ValueToString(val Value) string { case Uint64Kind: return integer(int64(val.(Uint64Value).Get())); case Float32Kind: - return "float32"; + return floatingpoint(float64(val.(Float32Value).Get())); case Float64Kind: - return "float64"; + return floatingpoint(float64(val.(Float64Value).Get())); case Float80Kind: return "float80"; case StringKind: return val.(StringValue).Get(); case PtrKind: - p := typ.(PtrType); - return ValueToString(p.Sub()); + v := val.(PtrValue); + return TypeToString(typ) + "(" + integer(int64(v.Addr())) + ")"; + case ArrayKind: + t := typ.(ArrayType); + v := val.(ArrayValue); + str += TypeToString(t); + str += "{"; + for i := 0; i < v.Len(); i++ { + if i > 0 { + str += ", " + } + str += ValueToString(v.Elem(i)); + } + str += "}"; + return str; + case MapKind: + t := typ.(MapType); + v := val.(ArrayValue); + str = TypeToString(t); + str += "{"; + str += ""; + str += "}"; + return str; + case ChanKind: + return "can't print chans yet"; + case StructKind: + t := typ.(StructType); + v := val.(StructValue); + str += TypeToString(t); // TODO: use the name? + str += "{"; + for i := 0; i < v.Len(); i++ { + if i > 0 { + str += ", " + } + str += ValueToString(v.Field(i)); + } + str += "}"; + return str; + case InterfaceKind: + return "can't print interfaces yet"; + case FuncKind: + return "can't print funcs yet"; default: panicln("reflect.ValueToString: can't print type ", val.Kind()); } diff --git a/usr/r/reflect/type.go b/usr/r/reflect/type.go index 9ed6c75e9e..39a3c3ae34 100644 --- a/usr/r/reflect/type.go +++ b/usr/r/reflect/type.go @@ -11,7 +11,7 @@ export type Type interface export func ExpandType(name string) Type -//export var GlobalTypeStrings = sys.typestrings; +export func typestrings() string // implemented in C; declared here export const ( MissingKind = iota; @@ -36,33 +36,39 @@ export const ( Uint8Kind; ) -var ptrsize int -var interfacesize int +var ptrsize uint64 +var interfacesize uint64 -var MissingString = "missing" // syntactic name for undefined type names +var MissingString = "$missing$" // syntactic name for undefined type names export type Type interface { Kind() int; - Size() int; + Size() uint64; } // -- Basic type BasicType struct{ + name string; kind int; - size int; + size uint64; +} + +func (t *BasicType) Name() string { + return t.name } func (t *BasicType) Kind() int { return t.kind } -func (t *BasicType) Size() int { +func (t *BasicType) Size() uint64 { return t.size } -func NewBasicType(k, size int) Type { +func NewBasicType(n string, k int, size uint64) Type { t := new(BasicType); + t.name = n; t.kind = k; t.size = size; return t; @@ -70,19 +76,19 @@ func NewBasicType(k, size int) Type { // Prebuilt basic types export var ( - Missing = NewBasicType(MissingKind, 1); - Int8 = NewBasicType(Int8Kind, 1); - Int16 = NewBasicType(Int16Kind, 2); - Int32 = NewBasicType(Int32Kind, 4); - Int64 = NewBasicType(Int64Kind, 8); - Uint8 = NewBasicType(Uint8Kind, 1); - Uint16 = NewBasicType(Uint16Kind, 2); - Uint32 = NewBasicType(Uint32Kind, 4); - Uint64 = NewBasicType(Uint64Kind, 8); - Float32 = NewBasicType(Float32Kind, 4); - Float64 = NewBasicType(Float64Kind, 8); - Float80 = NewBasicType(Float80Kind, 10); // TODO: strange size? - String = NewBasicType(StringKind, 8); // implemented as a pointer + Missing = NewBasicType(MissingString, MissingKind, 1); + Int8 = NewBasicType("int8", Int8Kind, 1); + Int16 = NewBasicType("int16", Int16Kind, 2); + Int32 = NewBasicType("int32", Int32Kind, 4); + Int64 = NewBasicType("int64", Int64Kind, 8); + Uint8 = NewBasicType("uint8", Uint8Kind, 1); + Uint16 = NewBasicType("uint16", Uint16Kind, 2); + Uint32 = NewBasicType("uint32", Uint32Kind, 4); + Uint64 = NewBasicType("uint64", Uint64Kind, 8); + Float32 = NewBasicType("float32", Float32Kind, 4); + Float64 = NewBasicType("float64", Float64Kind, 8); + Float80 = NewBasicType("float80", Float80Kind, 10); // TODO: strange size? + String = NewBasicType("string", StringKind, 8); // implemented as a pointer ) // Stub types allow us to defer evaluating type names until needed. @@ -126,7 +132,7 @@ func (t *PtrTypeStruct) Kind() int { return PtrKind } -func (t *PtrTypeStruct) Size() int { +func (t *PtrTypeStruct) Size() uint64 { return ptrsize } @@ -143,28 +149,34 @@ func NewPtrTypeStruct(sub *StubType) *PtrTypeStruct { // -- Array export type ArrayType interface { - Len() int; + Open() bool; + Len() uint64; Elem() Type; } type ArrayTypeStruct struct { elem *StubType; - len int; + open bool; // otherwise fixed size + len uint64; } func (t *ArrayTypeStruct) Kind() int { return ArrayKind } -func (t *ArrayTypeStruct) Size() int { - if t.len < 0 { +func (t *ArrayTypeStruct) Size() uint64 { + if t.open { return ptrsize // open arrays are pointers to structures } return t.len * t.elem.Get().Size(); } -func (t *ArrayTypeStruct) Len() int { - // -1 is open array? TODO +func (t *ArrayTypeStruct) Open() bool { + return t.open +} + +func (t *ArrayTypeStruct) Len() uint64 { + // what about open array? TODO return t.len } @@ -172,8 +184,9 @@ func (t *ArrayTypeStruct) Elem() Type { return t.elem.Get() } -func NewArrayTypeStruct(len int, elem *StubType) *ArrayTypeStruct { +func NewArrayTypeStruct(open bool, len uint64, elem *StubType) *ArrayTypeStruct { t := new(ArrayTypeStruct); + t.open = open; t.len = len; t.elem = elem; return t; @@ -195,7 +208,7 @@ func (t *MapTypeStruct) Kind() int { return MapKind } -func (t *MapTypeStruct) Size() int { +func (t *MapTypeStruct) Size() uint64 { panic("reflect.type: map.Size(): cannot happen"); return 0 } @@ -236,8 +249,8 @@ type ChanTypeStruct struct { func (t *ChanTypeStruct) Kind() int { return ChanKind } - -func (t *ChanTypeStruct) Size() int { + +func (t *ChanTypeStruct) Size() uint64 { panic("reflect.type: chan.Size(): cannot happen"); return 0 } @@ -261,14 +274,15 @@ func NewChanTypeStruct(dir int, elem *StubType) *ChanTypeStruct { // -- Struct export type StructType interface { - Field(int) (name string, typ Type); + Field(int) (name string, typ Type, offset uint64); Len() int; } type Field struct { name string; typ *StubType; - size int; + size uint64; + offset uint64; } type StructTypeStruct struct { @@ -280,26 +294,30 @@ func (t *StructTypeStruct) Kind() int { } // TODO: not portable; depends on 6g -func (t *StructTypeStruct) Size() int { - size := 0; +func (t *StructTypeStruct) Size() uint64 { + size := uint64(0); for i := 0; i < len(t.field); i++ { elemsize := t.field[i].typ.Get().Size(); // pad until at (elemsize mod 8) boundary align := elemsize - 1; - if align > 7 { // BUG: we know structs are at 8-aligned + if align > 7 { // BUG: we know structs are 8-aligned align = 7 } if align > 0 { size = (size + align) & ^align; } + t.field[i].offset = size; size += elemsize; } - size = (size + 7) & ^7; + size = (size + 7) & ((1<<64 - 1) & ^7); return size; } -func (t *StructTypeStruct) Field(i int) (name string, typ Type) { - return t.field[i].name, t.field[i].typ.Get() +func (t *StructTypeStruct) Field(i int) (name string, typ Type, offset uint64) { + if t.field[i].offset == 0 { + t.Size(); // will compute offsets + } + return t.field[i].name, t.field[i].typ.Get(), t.field[i].offset } func (t *StructTypeStruct) Len() int { @@ -315,7 +333,7 @@ func NewStructTypeStruct(field *[]Field) *StructTypeStruct { // -- Interface export type InterfaceType interface { - Field(int) (name string, typ Type); + Field(int) (name string, typ Type, offset uint64); Len() int; } @@ -323,8 +341,8 @@ type InterfaceTypeStruct struct { field *[]Field; } -func (t *InterfaceTypeStruct) Field(i int) (name string, typ Type) { - return t.field[i].name, t.field[i].typ.Get() +func (t *InterfaceTypeStruct) Field(i int) (name string, typ Type, offset uint64) { + return t.field[i].name, t.field[i].typ.Get(), 0 } func (t *InterfaceTypeStruct) Len() int { @@ -341,7 +359,7 @@ func (t *InterfaceTypeStruct) Kind() int { return InterfaceKind } -func (t *InterfaceTypeStruct) Size() int { +func (t *InterfaceTypeStruct) Size() uint64 { return interfacesize } @@ -361,7 +379,7 @@ func (t *FuncTypeStruct) Kind() int { return FuncKind } -func (t *FuncTypeStruct) Size() int { +func (t *FuncTypeStruct) Size() uint64 { panic("reflect.type: func.Size(): cannot happen"); return 0 } @@ -388,10 +406,11 @@ func NewFuncTypeStruct(in, out *StructTypeStruct) *FuncTypeStruct { var types *map[string] *Type // BUG TODO: should be Type not *Type // List of typename, typestring pairs -var typestrings *map[string] string +var typestring *map[string] string +var initialized bool = false // Map of basic types to prebuilt StubTypes -var basicstubs *map[string] *StubType +var basicstub *map[string] *StubType var MissingStub *StubType; @@ -414,11 +433,11 @@ func init() { Lock(); // not necessary because of init ordering but be safe. types = new(map[string] *Type); - typestrings = new(map[string] string); - basicstubs = new(map[string] *StubType); + typestring = new(map[string] string); + basicstub = new(map[string] *StubType); // Basics go into types table - types["missing"] = &Missing; + types[MissingString] = &Missing; types["int8"] = &Int8; types["int16"] = &Int16; types["int32"] = &Int32; @@ -434,21 +453,19 @@ func init() { // Basics get prebuilt stubs MissingStub = NewStubType(Missing); - basicstubs["missing"] = MissingStub; - basicstubs["int8"] = NewStubType(Int8); - basicstubs["int16"] = NewStubType(Int16); - basicstubs["int32"] = NewStubType(Int32); - basicstubs["int64"] = NewStubType(Int64); - basicstubs["uint8"] = NewStubType(Uint8); - basicstubs["uint16"] = NewStubType(Uint16); - basicstubs["uint32"] = NewStubType(Uint32); - basicstubs["uint64"] = NewStubType(Uint64); - basicstubs["float32"] = NewStubType(Float32); - basicstubs["float64"] = NewStubType(Float64); - basicstubs["float80"] = NewStubType(Float80); - basicstubs["string"] = NewStubType(String); - - typestrings["P.integer"] = "int32"; // TODO: for testing; remove + basicstub[MissingString] = MissingStub; + basicstub["int8"] = NewStubType(Int8); + basicstub["int16"] = NewStubType(Int16); + basicstub["int32"] = NewStubType(Int32); + basicstub["int64"] = NewStubType(Int64); + basicstub["uint8"] = NewStubType(Uint8); + basicstub["uint16"] = NewStubType(Uint16); + basicstub["uint32"] = NewStubType(Uint32); + basicstub["uint64"] = NewStubType(Uint64); + basicstub["float32"] = NewStubType(Float32); + basicstub["float64"] = NewStubType(Float64); + basicstub["float80"] = NewStubType(Float80); + basicstub["string"] = NewStubType(String); Unlock(); } @@ -557,7 +574,8 @@ func (p *Parser) Next() { func (p *Parser) Type() *StubType func (p *Parser) Array() *StubType { - size := -1; + size := uint64(0); + open := true; if p.token != "]" { if len(p.token) == 0 || !isdigit(p.token[0]) { return MissingStub @@ -565,16 +583,17 @@ func (p *Parser) Array() *StubType { // write our own (trivial and simpleminded) atoi to avoid dependency size = 0; for i := 0; i < len(p.token); i++ { - size = size * 10 + int(p.token[i]) - '0' + size = size * 10 + uint64(p.token[i]) - '0' } p.Next(); + open = false; } if p.token != "]" { return MissingStub } p.Next(); elemtype := p.Type(); - return NewStubType(NewArrayTypeStruct(size, elemtype)); + return NewStubType(NewArrayTypeStruct(open, size, elemtype)); } func (p *Parser) Map() *StubType { @@ -715,7 +734,7 @@ func (p *Parser) Type() *StubType { return MissingStub; } // must be an identifier. is it basic? if so, we have a stub - if s, ok := basicstubs[p.token]; ok { + if s, ok := basicstub[p.token]; ok { p.Next(); return s } @@ -743,12 +762,50 @@ export func ParseTypeString(str string) Type { return p.Type().Get(); } +// Create typestring map from reflect.typestrings() data. Lock is held. +func InitializeTypeStrings() { + if initialized { + return + } + initialized = true; + s := typestrings(); + slen := len(s); + for i := 0; i < slen; { + // "reflect.PtrType interface { Sub () (? reflect.Type) }\n" + // find the identifier + idstart := i; + for ; i < slen && s[i] != ' '; i++ { + } + if i == slen { + print("reflect.InitializeTypeStrings: bad identifier\n"); + return; + } + idend := i; + i++; + // find the end of the line, terminating the type + typestart := i; + for ; i < slen && s[i] != '\n'; i++ { + } + if i == slen { + print("reflect.InitializeTypeStrings: bad type string\n"); + return; + } + typeend := i; + i++; //skip newline + typestring[s[idstart:idend]] = s[typestart:typeend]; + } +} + // Look up type string associated with name. Lock is held. func TypeNameToTypeString(name string) string { - s, ok := typestrings[name]; + s, ok := typestring[name]; if !ok { - s = MissingString; - typestrings[name] = s; + InitializeTypeStrings(); + s, ok = typestring[name]; + if !ok { + s = MissingString; + typestring[name] = s; + } } return s } diff --git a/usr/r/reflect/typestring.c b/usr/r/reflect/typestring.c new file mode 100644 index 0000000000..a5e6398ad3 --- /dev/null +++ b/usr/r/reflect/typestring.c @@ -0,0 +1,12 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +extern char gotypestrings[]; // really a go String, but we don't have the definition here + +void FLUSH(void *v) { } + +void reflect·typestrings(void *s) { + s = gotypestrings; + FLUSH(&s); +} diff --git a/usr/r/reflect/value.go b/usr/r/reflect/value.go new file mode 100644 index 0000000000..30f5193e0f --- /dev/null +++ b/usr/r/reflect/value.go @@ -0,0 +1,810 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Reflection library. +// Handling values. + +package reflect + +import ( + "reflect"; +) + +type Addr uint64 // TODO: where are ptrint/intptr etc? + +export type Value interface { + Kind() int; + Type() Type; +} + +func NewValueAddr(typ Type, addr Addr) Value + +type Creator *(typ Type, addr Addr) Value + +// Conversion functions, implemented in assembler +func AddrToPtrAddr(Addr) *Addr +func PtrAddrToAddr(*Addr) Addr +func AddrToPtrInt8(Addr) *int8 +func PtrInt8ToAddr(*int8) Addr +func AddrToPtrInt16(Addr) *int16 +func PtrInt16ToAddr(*int16) Addr +func AddrToPtrInt32(Addr) *int32 +func PtrInt32ToAddr(*int32) Addr +func AddrToPtrInt64(Addr) *int64 +func PtrInt64ToAddr(*int64) Addr +func AddrToPtrUint8(Addr) *uint8 +func PtrUint8ToAddr(*uint8) Addr +func AddrToPtrUint16(Addr) *uint16 +func PtrUint16ToAddr(*uint16) Addr +func AddrToPtrUint32(Addr) *uint32 +func PtrUint32ToAddr(*uint32) Addr +func AddrToPtrUint64(Addr) *uint64 +func PtrUint64ToAddr(*uint64) Addr +func AddrToPtrFloat32(Addr) *float32 +func PtrFloat32ToAddr(*float32) Addr +func AddrToPtrFloat64(Addr) *float64 +func PtrFloat64ToAddr(*float64) Addr +func AddrToPtrFloat80(Addr) *float80 +func PtrFloat80ToAddr(*float80) Addr +func AddrToPtrString(Addr) *string +func PtrStringToAddr(*string) Addr + +// -- Int8 + +export type Int8Value interface { + Kind() int; + Get() int8; + Put(int8); + Type() Type; +} + +type Int8ValueStruct struct { + p *int8 +} + +func (v *Int8ValueStruct) Kind() int { + return Int8Kind +} + +func (v *Int8ValueStruct) Type() Type { + return Int8 +} + +func (v *Int8ValueStruct) Get() int8 { + return *v.p +} + +func (v *Int8ValueStruct) Put(i int8) { + *v.p = i +} + +func Int8Creator(typ Type, addr Addr) Value { + v := new(Int8ValueStruct); + v.p = AddrToPtrInt8(addr); + return v; +} + +// -- Int16 + +export type Int16Value interface { + Kind() int; + Get() int16; + Put(int16); + Type() Type; +} + +type Int16ValueStruct struct { + p *int16 +} + +func (v *Int16ValueStruct) Kind() int { + return Int16Kind +} + +func (v *Int16ValueStruct) Type() Type { + return Int16 +} + +func (v *Int16ValueStruct) Get() int16 { + return *v.p +} + +func (v *Int16ValueStruct) Put(i int16) { + *v.p = i +} + +func Int16Creator(typ Type, addr Addr) Value { + v := new(Int16ValueStruct); + v.p = AddrToPtrInt16(addr); + return v; +} + +// -- Int32 + +export type Int32Value interface { + Kind() int; + Get() int32; + Put(int32); + Type() Type; +} + +type Int32ValueStruct struct { + p *int32 +} + +func (v *Int32ValueStruct) Type() Type { + return Int32 +} + +func (v *Int32ValueStruct) Kind() int { + return Int32Kind +} + +func (v *Int32ValueStruct) Get() int32 { + return *v.p +} + +func (v *Int32ValueStruct) Put(i int32) { + *v.p = i +} + +func Int32Creator(typ Type, addr Addr) Value { + v := new(Int32ValueStruct); + v.p = AddrToPtrInt32(addr); + return v; +} + +// -- Int64 + +export type Int64Value interface { + Kind() int; + Get() int64; + Put(int64); + Type() Type; +} + +type Int64ValueStruct struct { + p *int64 +} + +func (v *Int64ValueStruct) Kind() int { + return Int64Kind +} + +func (v *Int64ValueStruct) Type() Type { + return Int64 +} + +func (v *Int64ValueStruct) Get() int64 { + return *v.p +} + +func (v *Int64ValueStruct) Put(i int64) { + *v.p = i +} + +func Int64Creator(typ Type, addr Addr) Value { + v := new(Int64ValueStruct); + v.p = AddrToPtrInt64(addr); + return v; +} + +// -- Uint8 + +export type Uint8Value interface { + Kind() int; + Get() uint8; + Put(uint8); + Type() Type; +} + +type Uint8ValueStruct struct { + p *uint8 +} + +func (v *Uint8ValueStruct) Kind() int { + return Uint8Kind +} + +func (v *Uint8ValueStruct) Type() Type { + return Uint8 +} + +func (v *Uint8ValueStruct) Get() uint8 { + return *v.p +} + +func (v *Uint8ValueStruct) Put(i uint8) { + *v.p = i +} + +func Uint8Creator(typ Type, addr Addr) Value { + v := new(Uint8ValueStruct); + v.p = AddrToPtrUint8(addr); + return v; +} + +// -- Uint16 + +export type Uint16Value interface { + Kind() int; + Get() uint16; + Put(uint16); + Type() Type; +} + +type Uint16ValueStruct struct { + p *uint16 +} + +func (v *Uint16ValueStruct) Kind() int { + return Uint16Kind +} + +func (v *Uint16ValueStruct) Type() Type { + return Uint16 +} + +func (v *Uint16ValueStruct) Get() uint16 { + return *v.p +} + +func (v *Uint16ValueStruct) Put(i uint16) { + *v.p = i +} + +func Uint16Creator(typ Type, addr Addr) Value { + v := new(Uint16ValueStruct); + v.p = AddrToPtrUint16(addr); + return v; +} + +// -- Uint32 + +export type Uint32Value interface { + Kind() int; + Get() uint32; + Put(uint32); + Type() Type; +} + +type Uint32ValueStruct struct { + p *uint32 +} + +func (v *Uint32ValueStruct) Kind() int { + return Uint32Kind +} + +func (v *Uint32ValueStruct) Type() Type { + return Uint32 +} + +func (v *Uint32ValueStruct) Get() uint32 { + return *v.p +} + +func (v *Uint32ValueStruct) Put(i uint32) { + *v.p = i +} + +func Uint32Creator(typ Type, addr Addr) Value { + v := new(Uint32ValueStruct); + v.p = AddrToPtrUint32(addr); + return v; +} + +// -- Uint64 + +export type Uint64Value interface { + Kind() int; + Get() uint64; + Put(uint64); + Type() Type; +} + +type Uint64ValueStruct struct { + p *uint64 +} + +func (v *Uint64ValueStruct) Kind() int { + return Uint64Kind +} + +func (v *Uint64ValueStruct) Type() Type { + return Uint64 +} + +func (v *Uint64ValueStruct) Get() uint64 { + return *v.p +} + +func (v *Uint64ValueStruct) Put(i uint64) { + *v.p = i +} + +func Uint64Creator(typ Type, addr Addr) Value { + v := new(Uint64ValueStruct); + v.p = AddrToPtrUint64(addr); + return v; +} + +// -- Float32 + +export type Float32Value interface { + Kind() int; + Get() float32; + Put(float32); + Type() Type; +} + +type Float32ValueStruct struct { + p *float32 +} + +func (v *Float32ValueStruct) Kind() int { + return Float32Kind +} + +func (v *Float32ValueStruct) Type() Type { + return Float32 +} + +func (v *Float32ValueStruct) Get() float32 { + return *v.p +} + +func (v *Float32ValueStruct) Put(f float32) { + *v.p = f +} + +func Float32Creator(typ Type, addr Addr) Value { + v := new(Float32ValueStruct); + v.p = AddrToPtrFloat32(addr); + return v; +} + +// -- Float64 + +export type Float64Value interface { + Kind() int; + Get() float64; + Put(float64); + Type() Type; +} + +type Float64ValueStruct struct { + p *float64 +} + +func (v *Float64ValueStruct) Kind() int { + return Float64Kind +} + +func (v *Float64ValueStruct) Type() Type { + return Float64 +} + +func (v *Float64ValueStruct) Get() float64 { + return *v.p +} + +func (v *Float64ValueStruct) Put(f float64) { + *v.p = f +} + +func Float64Creator(typ Type, addr Addr) Value { + v := new(Float64ValueStruct); + v.p = AddrToPtrFloat64(addr); + return v; +} + +// -- Float80 + +export type Float80Value interface { + Kind() int; + Get() float80; + Put(float80); + Type() Type; +} + +type Float80ValueStruct struct { + p *float80 +} + +func (v *Float80ValueStruct) Kind() int { + return Float80Kind +} + +func (v *Float80ValueStruct) Type() Type { + return Float80 +} + +/* +BUG: can't gen code for float80s +func (v *Float80ValueStruct) Get() float80 { + return *v.p + return 0; +} + +func (v *Float80ValueStruct) Put(f float80) { + *v.p = f +} +*/ + +func Float80Creator(typ Type, addr Addr) Value { + v := new(Float80ValueStruct); + v.p = AddrToPtrFloat80(addr); + return v; +} + +// -- String + +export type StringValue interface { + Kind() int; + Get() string; + Put(string); + Type() Type; +} + +type StringValueStruct struct { + p *string +} + +func (v *StringValueStruct) Kind() int { + return StringKind +} + +func (v *StringValueStruct) Type() Type { + return String +} + +func (v *StringValueStruct) Get() string { + return *v.p +} + +func (v *StringValueStruct) Put(s string) { + *v.p = s +} + +func StringCreator(typ Type, addr Addr) Value { + v := new(StringValueStruct); + v.p = AddrToPtrString(addr); + return v; +} + +// -- Pointer + +export type PtrValue interface { + Kind() int; + Sub() Value; + Type() Type; + Addr() Addr; +} + +type PtrValueStruct struct { + p *Addr; + typ Type; +} + +func (v *PtrValueStruct) Kind() int { + return PtrKind +} + +func (v *PtrValueStruct) Type() Type { + return v.typ +} + +func (v *PtrValueStruct) Sub() Value { + return NewValueAddr(v.typ, *v.p); +} + +func (v *PtrValueStruct) Addr() Addr { + return *v.p +} + +func PtrCreator(typ Type, addr Addr) Value { + v := new(PtrValueStruct); + v.p = AddrToPtrAddr(addr); + v.typ = typ; + return v; +} + +// -- Array TODO: finish and test + +export type ArrayValue interface { + Kind() int; + Type() Type; + Open() bool; + Len() int; + Elem(i int) Value; +} + +type OpenArrayValueStruct struct { + data Addr; + typ Type; + len int; +} + +func (v *OpenArrayValueStruct) Kind() int { + return ArrayKind +} + +func (v *OpenArrayValueStruct) Type() Type { + return v.typ +} + +func (v *OpenArrayValueStruct) Open() bool { + return true +} + +func (v *OpenArrayValueStruct) Len() int { + return v.len // TODO: probably want this to be dynamic +} + +func (v *OpenArrayValueStruct) Elem(i int) Value { + panic("open array value element"); + return nil +} + +type FixedArrayValueStruct struct { + data Addr; + typ Type; + len int; + elemtype Type; + elemsize uint64; +} + +func (v *FixedArrayValueStruct) Kind() int { + return ArrayKind +} + +func (v *FixedArrayValueStruct) Type() Type { + return v.typ +} + +func (v *FixedArrayValueStruct) Open() bool { + return false +} + +func (v *FixedArrayValueStruct) Len() int { + return v.len +} + +func (v *FixedArrayValueStruct) Elem(i int) Value { + return NewValueAddr(v.elemtype, v.data + uint64(i) * v.elemsize); + return nil +} + +func ArrayCreator(typ Type, addr Addr) Value { + arraytype := typ.(ArrayType); + if arraytype.Open() { + v := new(OpenArrayValueStruct); + v.data = addr; + v.typ = typ; + return v; + } + v := new(FixedArrayValueStruct); + v.data = addr; + v.typ = typ; + v.elemtype = arraytype.Elem(); + v.elemsize = arraytype.Len(); + return v; +} + +// -- Map TODO: finish and test + +export type MapValue interface { + Kind() int; + Type() Type; + Len() int; + Elem(key Value) Value; +} + +type MapValueStruct struct { + data Addr; + typ Type; + len int; +} + +func (v *MapValueStruct) Kind() int { + return MapKind +} + +func (v *MapValueStruct) Type() Type { + return v.typ +} + +func (v *MapValueStruct) Len() int { + return v.len // TODO: probably want this to be dynamic +} + +func (v *MapValueStruct) Elem(key Value) Value { + panic("map value element"); + return nil +} + +func MapCreator(typ Type, addr Addr) Value { + arraytype := typ.(MapType); + v := new(MapValueStruct); + v.data = addr; + v.typ = typ; + return v; +} + +// -- Chan + +export type ChanValue interface { + Kind() int; + Type() Type; +} + +type ChanValueStruct struct { + data Addr; + typ Type; + len int; +} + +func (v *ChanValueStruct) Kind() int { + return ChanKind +} + +func (v *ChanValueStruct) Type() Type { + return v.typ +} + +func ChanCreator(typ Type, addr Addr) Value { + v := new(ChanValueStruct); + v.data = addr; + v.typ = typ; + return v; +} + +// -- Struct + +export type StructValue interface { + Kind() int; + Type() Type; + Len() int; + Field(i int) Value; +} + +type StructValueStruct struct { + typ Type; + field *[]Value; +} + +func (v *StructValueStruct) Kind() int { + return StructKind +} + +func (v *StructValueStruct) Type() Type { + return v.typ +} + +func (v *StructValueStruct) Len() int { + return len(v.field) +} + +func (v *StructValueStruct) Field(i int) Value { + return v.field[i] +} + +func StructCreator(typ Type, addr Addr) Value { + t := typ.(StructType); + v := new(StructValueStruct); + nfield := t.Len(); + v.field = new([]Value, nfield); + for i := 0; i < nfield; i++ { + name, ftype, offset := t.Field(i); + v.field[i] = NewValueAddr(ftype, addr + offset); + } + v.typ = typ; + return v; +} + +// -- Interface + +export type InterfaceValue interface { + Kind() int; + Type() Type; +} + +type InterfaceValueInterface struct { + data Addr; + typ Type; +} + +func (v *InterfaceValueInterface) Kind() int { + return InterfaceKind +} + +func (v *InterfaceValueInterface) Type() Type { + return v.typ +} + +func InterfaceCreator(typ Type, addr Addr) Value { + v := new(InterfaceValueInterface); + v.data = addr; + v.typ = typ; + return v; +} + +// -- Func + +export type FuncValue interface { + Kind() int; + Type() Type; +} + +type FuncValueFunc struct { + data Addr; + typ Type; +} + +func (v *FuncValueFunc) Kind() int { + return FuncKind +} + +func (v *FuncValueFunc) Type() Type { + return v.typ +} + +func FuncCreator(typ Type, addr Addr) Value { + v := new(FuncValueFunc); + v.data = addr; + v.typ = typ; + return v; +} + +var creator *map[int] Creator + +func init() { + creator = new(map[int] Creator); + creator[Int8Kind] = &Int8Creator; + creator[Int16Kind] = &Int16Creator; + creator[Int32Kind] = &Int32Creator; + creator[Int64Kind] = &Int64Creator; + creator[Uint8Kind] = &Uint8Creator; + creator[Uint16Kind] = &Uint16Creator; + creator[Uint32Kind] = &Uint32Creator; + creator[Uint64Kind] = &Uint64Creator; + creator[Float32Kind] = &Float32Creator; + creator[Float64Kind] = &Float64Creator; + creator[Float80Kind] = &Float80Creator; + creator[StringKind] = &StringCreator; + creator[PtrKind] = &PtrCreator; + creator[ArrayKind] = &ArrayCreator; + creator[MapKind] = &MapCreator; + creator[ChanKind] = &ChanCreator; + creator[StructKind] = &StructCreator; + creator[InterfaceKind] = &InterfaceCreator; + creator[FuncKind] = &FuncCreator; +} + +func NewValueAddr(typ Type, addr Addr) Value { + c, ok := creator[typ.Kind()]; + if !ok { + panicln("no creator for type" , typ.Kind()); + } + return c(typ, addr); +} + +// TODO: do this better +export func NewInitValue(typ Type) Value { + size := typ.Size(); + if size == 0 { + size = 1; + } + data := new([]uint8, size); + return NewValueAddr(typ, PtrUint8ToAddr(&data[0])); +} + +// TODO: do this better +export func NewValue(e interface {}) Value { +// typestring, addr := sys.whathe(e); +// typ := ParseTypeString(typestring); +// return NewValueAddr(typ, addr); +return nil +}