summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRob Pike <r@golang.org>2008-10-22 17:12:07 -0700
committerRob Pike <r@golang.org>2008-10-22 17:12:07 -0700
commit56d93449c174ccb49a87193c17dfd5630261fc0c (patch)
tree14959b40e9b74299b5a069a9639591eff3000d50 /src
parent7b904af284aab3b669e41a9df0a7a2b8240710a6 (diff)
downloadgolang-56d93449c174ccb49a87193c17dfd5630261fc0c.tar.gz
move reflection code into final place.
this is just a branch. next cl will update and add to build R=rsc DELTA=4528 (2264 added, 2264 deleted, 0 changed) OCL=17670 CL=17672
Diffstat (limited to 'src')
-rw-r--r--src/lib/reflect/Makefile56
-rw-r--r--src/lib/reflect/cast_amd64.s133
-rwxr-xr-xsrc/lib/reflect/gencast.sh36
-rw-r--r--src/lib/reflect/main.go155
-rw-r--r--src/lib/reflect/tostring.go199
-rw-r--r--src/lib/reflect/type.go870
-rw-r--r--src/lib/reflect/typestring.c12
-rw-r--r--src/lib/reflect/value.go822
8 files changed, 2283 insertions, 0 deletions
diff --git a/src/lib/reflect/Makefile b/src/lib/reflect/Makefile
new file mode 100644
index 000000000..b0927a3b8
--- /dev/null
+++ b/src/lib/reflect/Makefile
@@ -0,0 +1,56 @@
+# 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.
+
+# DO NOT EDIT. Automatically generated by gobuild.
+# gobuild -m reflect tostring.go type.go value.go cast_amd64.s\
+# typestring.c
+O=6
+GC=$(O)g
+CC=$(O)c -w
+AS=$(O)a
+AR=$(O)ar
+
+PKG=$(GOROOT)/pkg/reflect.a
+
+install: $(PKG)
+
+nuke: clean
+ rm -f $(PKG)
+
+clean:
+ rm -f *.$O *.a
+
+%.$O: %.go
+ $(GC) $*.go
+
+%.$O: %.c
+ $(CC) $*.c
+
+%.$O: %.s
+ $(AS) $*.s
+
+
+O1=\
+ type.$O\
+ cast_amd64.$O\
+ typestring.$O\
+
+O2=\
+ value.$O\
+
+O3=\
+ tostring.$O\
+
+$(PKG): a1 a2 a3
+a1: $(O1)
+ $(AR) grc $(PKG) $(O1)
+a2: $(O2)
+ $(AR) grc $(PKG) $(O2)
+a3: $(O3)
+ $(AR) grc $(PKG) $(O3)
+
+$(O1): nuke
+$(O2): a1
+$(O3): a2
+
diff --git a/src/lib/reflect/cast_amd64.s b/src/lib/reflect/cast_amd64.s
new file mode 100644
index 000000000..1de31dd04
--- /dev/null
+++ b/src/lib/reflect/cast_amd64.s
@@ -0,0 +1,133 @@
+// Conversion operators - really just casts
+// *** Created by gencast.sh - Do Not Edit ***
+
+TEXT reflect·AddrToPtrAddr(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·PtrAddrToAddr(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·AddrToPtrInt8(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·PtrInt8ToAddr(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·AddrToPtrInt16(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·PtrInt16ToAddr(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·AddrToPtrInt32(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·PtrInt32ToAddr(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·AddrToPtrInt64(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·PtrInt64ToAddr(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·AddrToPtrUint8(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·PtrUint8ToAddr(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·AddrToPtrUint16(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·PtrUint16ToAddr(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·AddrToPtrUint32(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·PtrUint32ToAddr(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·AddrToPtrUint64(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·PtrUint64ToAddr(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·AddrToPtrFloat32(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·PtrFloat32ToAddr(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·AddrToPtrFloat64(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·PtrFloat64ToAddr(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·AddrToPtrFloat80(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·PtrFloat80ToAddr(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·AddrToPtrString(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
+TEXT reflect·PtrStringToAddr(SB),7,$-8
+ MOVQ 8(SP), AX
+ MOVQ AX, 16(SP)
+ RET
+
diff --git a/src/lib/reflect/gencast.sh b/src/lib/reflect/gencast.sh
new file mode 100755
index 000000000..e3871a531
--- /dev/null
+++ b/src/lib/reflect/gencast.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# 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.
+
+awk '
+BEGIN {
+ print("// Conversion operators - really just casts")
+ print("// *** Created by gencast.sh - Do Not Edit ***\n")}
+{
+ print("TEXT reflect·AddrToPtr" $0 "(SB),7,$-8")
+ print("\tMOVQ 8(SP), AX")
+ print("\tMOVQ AX, 16(SP)")
+ print("\tRET")
+ print("")
+ print("TEXT reflect·Ptr" $0 "ToAddr(SB),7,$-8")
+ print("\tMOVQ 8(SP), AX")
+ print("\tMOVQ AX, 16(SP)")
+ print("\tRET")
+ print("")
+}
+' > cast_$GOARCH.s << '!'
+Addr
+Int8
+Int16
+Int32
+Int64
+Uint8
+Uint16
+Uint32
+Uint64
+Float32
+Float64
+Float80
+String
+!
diff --git a/src/lib/reflect/main.go b/src/lib/reflect/main.go
new file mode 100644
index 000000000..c00f2b975
--- /dev/null
+++ b/src/lib/reflect/main.go
@@ -0,0 +1,155 @@
+// 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.
+
+package main
+
+import (
+ "reflect"
+)
+
+func typedump(s string) {
+ t := reflect.ParseTypeString("", s);
+ print(reflect.TypeToString(t, true),"; size = ", t.Size(), "\n");
+}
+
+func valuedump(s string) {
+ t := reflect.ParseTypeString("", s);
+ v := reflect.NewInitValue(t);
+ switch v.Kind() {
+ case reflect.Int8Kind:
+ v.(reflect.Int8Value).Put(8);
+ case reflect.Int16Kind:
+ v.(reflect.Int16Value).Put(16);
+ case reflect.Int32Kind:
+ v.(reflect.Int32Value).Put(32);
+ case reflect.Int64Kind:
+ v.(reflect.Int64Value).Put(64);
+ case reflect.Uint8Kind:
+ v.(reflect.Uint8Value).Put(8);
+ case reflect.Uint16Kind:
+ v.(reflect.Uint16Value).Put(16);
+ case reflect.Uint32Kind:
+ v.(reflect.Uint32Value).Put(32);
+ case reflect.Uint64Kind:
+ v.(reflect.Uint64Value).Put(64);
+ case reflect.Float32Kind:
+ v.(reflect.Float32Value).Put(32.0);
+ case reflect.Float64Kind:
+ 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; c string; d *int }
+
+func main() {
+ var s string;
+ var t reflect.Type;
+
+if false{
+ typedump("int8");
+ typedump("int16");
+ typedump("int32");
+ typedump("int64");
+ typedump("uint8");
+ typedump("uint16");
+ typedump("uint32");
+ typedump("uint64");
+ typedump("float32");
+ typedump("float64");
+ typedump("float80");
+ typedump("int8");
+ typedump("**int8");
+ typedump("**P.integer");
+ typedump("[32]int32");
+ typedump("[]int8");
+ typedump("*map[string]int32");
+ typedump("*chan<-string");
+ typedump("struct {c *chan *int32; d float32}");
+ typedump("*(a int8, b int32)");
+ typedump("struct {c *(? *chan *P.integer, ? *int8)}");
+ typedump("struct {a int8; b int32}");
+ typedump("struct {a int8; b int8; b int32}");
+ typedump("struct {a int8; b int8; c int8; b int32}");
+ typedump("struct {a int8; b int8; c int8; d int8; b int32}");
+ typedump("struct {a int8; b int8; c int8; d int8; e int8; b int32}");
+
+ valuedump("int8");
+ valuedump("int16");
+ valuedump("int32");
+ valuedump("int64");
+ valuedump("uint8");
+ 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}");
+}
+{ var tmp = 123;
+ value := reflect.NewValue(tmp);
+ println(reflect.ValueToString(value));
+}
+{ var tmp = 123.4;
+ value := reflect.NewValue(tmp);
+ println(reflect.ValueToString(value));
+}
+{ var tmp = "abc";
+ value := reflect.NewValue(tmp);
+ println(reflect.ValueToString(value));
+}
+{
+ var i int = 7;
+ var tmp = &T{123, 456.0, "hello", &i};
+ value := reflect.NewValue(tmp);
+ println(reflect.ValueToString(value.(reflect.PtrValue).Sub()));
+}
+{
+ type C chan *T; // TODO: should not be necessary
+ var tmp = new(C);
+ value := reflect.NewValue(tmp);
+ println(reflect.ValueToString(value));
+}
+{
+ type A [10]int;
+ var tmp A = A{1,2,3,4,5,6,7,8,9,10};
+ value := reflect.NewValue(&tmp);
+ println(reflect.TypeToString(value.Type().(reflect.PtrType).Sub(), true));
+ println(reflect.TypeToString(value.(reflect.PtrValue).Sub().Type(), true));
+ println(reflect.ValueToString(value.(reflect.PtrValue).Sub()));
+ value.(reflect.PtrValue).Sub().(reflect.ArrayValue).Elem(4).(reflect.Int32Value).Put(123);
+ println(reflect.ValueToString(value.(reflect.PtrValue).Sub()));
+}
+{
+ type AA []int;
+ tmp1 := [10]int{1,2,3,4,5,6,7,8,9,10};
+ var tmp *AA = &tmp1;
+ value := reflect.NewValue(tmp);
+ println(reflect.TypeToString(value.Type().(reflect.PtrType).Sub(), true));
+ println(reflect.TypeToString(value.(reflect.PtrValue).Sub().Type(), true));
+ println(reflect.ValueToString(value.(reflect.PtrValue).Sub()));
+ value.(reflect.PtrValue).Sub().(reflect.ArrayValue).Elem(4).(reflect.Int32Value).Put(123);
+ println(reflect.ValueToString(value.(reflect.PtrValue).Sub()));
+}
+}
diff --git a/src/lib/reflect/tostring.go b/src/lib/reflect/tostring.go
new file mode 100644
index 000000000..ca3ada9fd
--- /dev/null
+++ b/src/lib/reflect/tostring.go
@@ -0,0 +1,199 @@
+// 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.
+// Formatting of types and values for debugging.
+
+package reflect
+
+import (
+ "reflect";
+ "strings";
+)
+
+export func TypeToString(typ Type, expand bool) string
+export func ValueToString(val Value) string
+
+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 < t.Len(); i++ {
+ str1, typ, offset := t.Field(i);
+ str1 += " " + TypeToString(typ, false);
+ if i < t.Len() - 1 {
+ str1 += sep + " ";
+ }
+ str += str1;
+ }
+ return str;
+}
+
+func TypeToString(typ Type, expand bool) string {
+ var str string;
+ if name := typ.Name(); !expand && name != "" {
+ return name
+ }
+ switch(typ.Kind()) {
+ case MissingKind:
+ return "$missing$";
+ case Int8Kind:
+ return "int8";
+ case Int16Kind:
+ return "int16";
+ case Int32Kind:
+ return "int32";
+ case Int64Kind:
+ return "int64";
+ case Uint8Kind:
+ return "uint8";
+ case Uint16Kind:
+ return "uint16";
+ case Uint32Kind:
+ return "uint32";
+ case Uint64Kind:
+ return "uint64";
+ case Float32Kind:
+ return "float32";
+ case Float64Kind:
+ return "float64";
+ case Float80Kind:
+ return "float80";
+ case StringKind:
+ return "string";
+ case PtrKind:
+ p := typ.(PtrType);
+ return "*" + TypeToString(p.Sub(), false);
+ case ArrayKind:
+ a := typ.(ArrayType);
+ if a.Open() {
+ str = "[]"
+ } else {
+ str = "[" + strings.ltoa(int64(a.Len())) + "]"
+ }
+ return str + TypeToString(a.Elem(), false);
+ case MapKind:
+ m := typ.(MapType);
+ str = "map[" + TypeToString(m.Key(), false) + "]";
+ return str + TypeToString(m.Elem(), false);
+ case ChanKind:
+ c := typ.(ChanType);
+ switch c.Dir() {
+ case RecvDir:
+ str = "<-chan";
+ case SendDir:
+ str = "chan<-";
+ case BothDir:
+ str = "chan";
+ default:
+ panicln("reflect.TypeToString: unknown chan direction");
+ }
+ return str + TypeToString(c.Elem(), false);
+ case StructKind:
+ return "struct{" + TypeFieldsToString(typ, ";") + "}";
+ case InterfaceKind:
+ return "interface{" + TypeFieldsToString(typ, ";") + "}";
+ case FuncKind:
+ f := typ.(FuncType);
+ str = "(" + TypeFieldsToString(f.In(), ",") + ")";
+ if f.Out() != nil {
+ str += "(" + TypeFieldsToString(f.Out(), ",") + ")";
+ }
+ return str;
+ default:
+ panicln("reflect.TypeToString: can't print type ", typ.Kind());
+ }
+ return "reflect.TypeToString: can't happen";
+}
+
+// TODO: want an unsigned one too
+func integer(v int64) string {
+ return strings.ltoa(v);
+}
+
+func floatingpoint(v float64) string {
+ return strings.dtoa(v);
+}
+
+func ValueToString(val Value) string {
+ var str string;
+ typ := val.Type();
+ switch(val.Kind()) {
+ case MissingKind:
+ return "missing";
+ case Int8Kind:
+ return integer(int64(val.(Int8Value).Get()));
+ case Int16Kind:
+ return integer(int64(val.(Int16Value).Get()));
+ case Int32Kind:
+ return integer(int64(val.(Int32Value).Get()));
+ case Int64Kind:
+ return integer(int64(val.(Int64Value).Get()));
+ case Uint8Kind:
+ return integer(int64(val.(Uint8Value).Get()));
+ case Uint16Kind:
+ return integer(int64(val.(Uint16Value).Get()));
+ case Uint32Kind:
+ return integer(int64(val.(Uint32Value).Get()));
+ case Uint64Kind:
+ return integer(int64(val.(Uint64Value).Get()));
+ case Float32Kind:
+ return floatingpoint(float64(val.(Float32Value).Get()));
+ case Float64Kind:
+ return floatingpoint(float64(val.(Float64Value).Get()));
+ case Float80Kind:
+ return "float80";
+ case StringKind:
+ return val.(StringValue).Get();
+ case PtrKind:
+ v := val.(PtrValue);
+ return TypeToString(typ, false) + "(" + integer(int64(v.Indirect())) + ")";
+ case ArrayKind:
+ t := typ.(ArrayType);
+ v := val.(ArrayValue);
+ str += TypeToString(t, false);
+ str += "{";
+ for i := uint64(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, false);
+ str += "{";
+ str += "<can't iterate on maps>";
+ str += "}";
+ return str;
+ case ChanKind:
+ return "can't print chans yet";
+ case StructKind:
+ t := typ.(StructType);
+ v := val.(StructValue);
+ str += TypeToString(t, false);
+ 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());
+ }
+ return "reflect.ValueToString: can't happen";
+}
diff --git a/src/lib/reflect/type.go b/src/lib/reflect/type.go
new file mode 100644
index 000000000..c69a3394e
--- /dev/null
+++ b/src/lib/reflect/type.go
@@ -0,0 +1,870 @@
+// 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.
+// Types and parsing of type strings.
+
+package reflect
+
+export type Type interface
+
+export func ExpandType(name string) Type
+
+export func typestrings() string // implemented in C; declared here
+
+export const (
+ MissingKind = iota;
+ ArrayKind;
+ ChanKind;
+ Float32Kind;
+ Float64Kind;
+ Float80Kind;
+ FuncKind;
+ Int16Kind;
+ Int32Kind;
+ Int64Kind;
+ Int8Kind;
+ InterfaceKind;
+ MapKind;
+ PtrKind;
+ StringKind;
+ StructKind;
+ Uint16Kind;
+ Uint32Kind;
+ Uint64Kind;
+ Uint8Kind;
+)
+
+var ptrsize uint64
+var interfacesize uint64
+
+var MissingString = "$missing$" // syntactic name for undefined type names
+
+export type Type interface {
+ Kind() int;
+ Name() string;
+ Size() uint64;
+}
+
+// -- Basic
+
+type BasicType struct{
+ kind int;
+ name string;
+ size uint64;
+}
+
+func (t *BasicType) Name() string {
+ return t.name
+}
+
+func (t *BasicType) Kind() int {
+ return t.kind
+}
+
+func (t *BasicType) Size() uint64 {
+ return t.size
+}
+
+func NewBasicType(n string, k int, size uint64) Type {
+ t := new(BasicType);
+ t.name = n;
+ t.kind = k;
+ t.size = size;
+ return t;
+}
+
+// Prebuilt basic types
+export var (
+ 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.
+// If the name is empty, the type must be non-nil.
+
+type StubType struct {
+ name string;
+ typ Type;
+}
+
+func (t *StubType) Get() Type {
+ if t.typ == nil {
+ t.typ = ExpandType(t.name)
+ }
+ return t.typ
+}
+
+func NewStubType(name string, t Type) *StubType {
+ s := new(StubType);
+ s.name = name;
+ s.typ = t;
+ return s;
+}
+
+// -- Pointer
+
+export type PtrType interface {
+ Sub() Type
+}
+
+type PtrTypeStruct struct {
+ name string;
+ sub *StubType;
+}
+
+func (t *PtrTypeStruct) Kind() int {
+ return PtrKind
+}
+
+func (t *PtrTypeStruct) Name() string {
+ return t.name
+}
+
+func (t *PtrTypeStruct) Size() uint64 {
+ return ptrsize
+}
+
+func (t *PtrTypeStruct) Sub() Type {
+ return t.sub.Get()
+}
+
+func NewPtrTypeStruct(name string, sub *StubType) *PtrTypeStruct {
+ t := new(PtrTypeStruct);
+ t.name = name;
+ t.sub = sub;
+ return t;
+}
+
+// -- Array
+
+export type ArrayType interface {
+ Open() bool;
+ Len() uint64;
+ Elem() Type;
+}
+
+type ArrayTypeStruct struct {
+ name string;
+ elem *StubType;
+ open bool; // otherwise fixed size
+ len uint64;
+}
+
+func (t *ArrayTypeStruct) Kind() int {
+ return ArrayKind
+}
+
+func (t *ArrayTypeStruct) Name() string {
+ return t.name
+}
+
+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) Open() bool {
+ return t.open
+}
+
+func (t *ArrayTypeStruct) Len() uint64 {
+ // what about open array? TODO
+ return t.len
+}
+
+func (t *ArrayTypeStruct) Elem() Type {
+ return t.elem.Get()
+}
+
+func NewArrayTypeStruct(name string, open bool, len uint64, elem *StubType) *ArrayTypeStruct {
+ t := new(ArrayTypeStruct);
+ t.name = name;
+ t.open = open;
+ t.len = len;
+ t.elem = elem;
+ return t;
+}
+
+// -- Map
+
+export type MapType interface {
+ Key() Type;
+ Elem() Type;
+}
+
+type MapTypeStruct struct {
+ name string;
+ key *StubType;
+ elem *StubType;
+}
+
+func (t *MapTypeStruct) Kind() int {
+ return MapKind
+}
+
+func (t *MapTypeStruct) Name() string {
+ return t.name
+}
+
+func (t *MapTypeStruct) Size() uint64 {
+ panic("reflect.type: map.Size(): cannot happen");
+ return 0
+}
+
+func (t *MapTypeStruct) Key() Type {
+ return t.key.Get()
+}
+
+func (t *MapTypeStruct) Elem() Type {
+ return t.elem.Get()
+}
+
+func NewMapTypeStruct(name string, key, elem *StubType) *MapTypeStruct {
+ t := new(MapTypeStruct);
+ t.name = name;
+ t.key = key;
+ t.elem = elem;
+ return t;
+}
+
+// -- Chan
+
+export type ChanType interface {
+ Dir() int;
+ Elem() Type;
+}
+
+export const ( // channel direction
+ SendDir = 1 << iota;
+ RecvDir;
+ BothDir = SendDir | RecvDir;
+)
+
+type ChanTypeStruct struct {
+ name string;
+ elem *StubType;
+ dir int;
+}
+
+func (t *ChanTypeStruct) Kind() int {
+ return ChanKind
+}
+
+func (t *ChanTypeStruct) Name() string {
+ return t.name
+}
+
+func (t *ChanTypeStruct) Size() uint64 {
+ panic("reflect.type: chan.Size(): cannot happen");
+ return 0
+}
+
+func (t *ChanTypeStruct) Dir() int {
+ // -1 is open array? TODO
+ return t.dir
+}
+
+func (t *ChanTypeStruct) Elem() Type {
+ return t.elem.Get()
+}
+
+func NewChanTypeStruct(name string, dir int, elem *StubType) *ChanTypeStruct {
+ t := new(ChanTypeStruct);
+ t.name = name;
+ t.dir = dir;
+ t.elem = elem;
+ return t;
+}
+
+// -- Struct
+
+export type StructType interface {
+ Field(int) (name string, typ Type, offset uint64);
+ Len() int;
+}
+
+type Field struct {
+ name string;
+ typ *StubType;
+ size uint64;
+ offset uint64;
+}
+
+type StructTypeStruct struct {
+ name string;
+ field *[]Field;
+}
+
+func (t *StructTypeStruct) Kind() int {
+ return StructKind
+}
+
+func (t *StructTypeStruct) Name() string {
+ return t.name
+}
+
+// TODO: not portable; depends on 6g
+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 8-aligned
+ align = 7
+ }
+ if align > 0 {
+ size = (size + align) & ^align;
+ }
+ t.field[i].offset = size;
+ size += elemsize;
+ }
+ size = (size + 7) & ((1<<64 - 1) & ^7);
+ return size;
+}
+
+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 {
+ return len(t.field)
+}
+
+func NewStructTypeStruct(name string, field *[]Field) *StructTypeStruct {
+ t := new(StructTypeStruct);
+ t.name = name;
+ t.field = field;
+ return t;
+}
+
+// -- Interface
+
+export type InterfaceType interface {
+ Field(int) (name string, typ Type, offset uint64);
+ Len() int;
+}
+
+type InterfaceTypeStruct struct {
+ name string;
+ field *[]Field;
+}
+
+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 {
+ return len(t.field)
+}
+
+func NewInterfaceTypeStruct(name string, field *[]Field) *InterfaceTypeStruct {
+ t := new(InterfaceTypeStruct);
+ t.name = name;
+ t.field = field;
+ return t;
+}
+
+func (t *InterfaceTypeStruct) Kind() int {
+ return InterfaceKind
+}
+
+func (t *InterfaceTypeStruct) Name() string {
+ return t.name
+}
+
+func (t *InterfaceTypeStruct) Size() uint64 {
+ return interfacesize
+}
+
+// -- Func
+
+export type FuncType interface {
+ In() StructType;
+ Out() StructType;
+}
+
+type FuncTypeStruct struct {
+ name string;
+ in *StructTypeStruct;
+ out *StructTypeStruct;
+}
+
+func (t *FuncTypeStruct) Kind() int {
+ return FuncKind
+}
+
+func (t *FuncTypeStruct) Name() string {
+ return t.name
+}
+
+func (t *FuncTypeStruct) Size() uint64 {
+ panic("reflect.type: func.Size(): cannot happen");
+ return 0
+}
+
+func (t *FuncTypeStruct) In() StructType {
+ return t.in
+}
+
+func (t *FuncTypeStruct) Out() StructType {
+ if t.out == nil { // nil.(StructType) != nil so make sure caller sees real nil
+ return nil
+ }
+ return t.out
+}
+
+func NewFuncTypeStruct(name string, in, out *StructTypeStruct) *FuncTypeStruct {
+ t := new(FuncTypeStruct);
+ t.name = name;
+ t.in = in;
+ t.out = out;
+ return t;
+}
+
+// Cache of expanded types keyed by type name.
+var types *map[string] *Type // BUG TODO: should be Type not *Type
+
+// List of typename, typestring pairs
+var typestring *map[string] string
+var initialized bool = false
+
+// Map of basic types to prebuilt StubTypes
+var basicstub *map[string] *StubType
+
+var MissingStub *StubType;
+
+// The database stored in the maps is global; use locking to guarantee safety.
+var lockchan *chan bool // Channel with buffer of 1, used as a mutex
+
+func Lock() {
+ lockchan <- true // block if buffer is full
+}
+
+func Unlock() {
+ <-lockchan // release waiters
+}
+
+func init() {
+ ptrsize = 8; // TODO: compute this
+ interfacesize = 2*ptrsize; // TODO: compute this
+
+ lockchan = new(chan bool, 1); // unlocked at creation - buffer is empty
+ Lock(); // not necessary because of init ordering but be safe.
+
+ types = new(map[string] *Type);
+ typestring = new(map[string] string);
+ basicstub = new(map[string] *StubType);
+
+ // Basics go into types table
+ types[MissingString] = &Missing;
+ types["int8"] = &Int8;
+ types["int16"] = &Int16;
+ types["int32"] = &Int32;
+ types["int64"] = &Int64;
+ types["uint8"] = &Uint8;
+ types["uint16"] = &Uint16;
+ types["uint32"] = &Uint32;
+ types["uint64"] = &Uint64;
+ types["float32"] = &Float32;
+ types["float64"] = &Float64;
+ types["float80"] = &Float80;
+ types["string"] = &String;
+
+ // Basics get prebuilt stubs
+ MissingStub = NewStubType(MissingString, Missing);
+ basicstub[MissingString] = MissingStub;
+ basicstub["int8"] = NewStubType("int8", Int8);
+ basicstub["int16"] = NewStubType("int16", Int16);
+ basicstub["int32"] = NewStubType("int32", Int32);
+ basicstub["int64"] = NewStubType("int64", Int64);
+ basicstub["uint8"] = NewStubType("uint8", Uint8);
+ basicstub["uint16"] = NewStubType("uint16", Uint16);
+ basicstub["uint32"] = NewStubType("uint32", Uint32);
+ basicstub["uint64"] = NewStubType("uint64", Uint64);
+ basicstub["float32"] = NewStubType("float32", Float32);
+ basicstub["float64"] = NewStubType("float64", Float64);
+ basicstub["float80"] = NewStubType("float80", Float80);
+ basicstub["string"] = NewStubType("string", String);
+
+ Unlock();
+}
+
+/*
+ Grammar
+
+ stubtype = - represent as StubType when possible
+ type
+ identifier =
+ name
+ '?'
+ type =
+ basictypename - int8, string, etc.
+ typename
+ arraytype
+ structtype
+ interfacetype
+ chantype
+ maptype
+ pointertype
+ functiontype
+ typename =
+ name '.' name
+ fieldlist =
+ [ field { [ ',' | ';' ] field } ]
+ field =
+ identifier stubtype
+ arraytype =
+ '[' [ number ] ']' stubtype
+ structtype =
+ 'struct' '{' fieldlist '}'
+ interfacetype =
+ 'interface' '{' fieldlist '}'
+ chantype =
+ '<-' chan stubtype
+ chan '<-' stubtype
+ chan stubtype
+ maptype =
+ 'map' '[' stubtype ']' stubtype
+ pointertype =
+ '*' stubtype
+ functiontype =
+ '(' fieldlist ')'
+
+*/
+
+// Helper functions for token scanning
+func isdigit(c uint8) bool {
+ return '0' <= c && c <= '9'
+}
+
+func special(c uint8) bool {
+ s := "*[](){}<;,"; // Note: '.' is not in this list. "P.T" is an identifer, as is "?".
+ for i := 0; i < len(s); i++ {
+ if c == s[i] {
+ return true
+ }
+ }
+ return false;
+}
+
+// Simple parser for type strings
+type Parser struct {
+ str string; // string being parsed
+ token string; // the token being parsed now
+ index int; // next character position in str
+}
+
+// Load next token into p.token
+func (p *Parser) Next() {
+ token := "";
+ for ; p.index < len(p.str) && p.str[p.index] == ' '; p.index++ {
+ }
+ if p.index >= len(p.str) {
+ p.token = "";
+ return;
+ }
+ start := p.index;
+ c, w := sys.stringtorune(p.str, p.index);
+ p.index += w;
+ switch {
+ case c == '<':
+ if p.index < len(p.str) && p.str[p.index] == '-' {
+ p.index++;
+ p.token = "<-";
+ return;
+ }
+ fallthrough; // shouldn't happen but let the parser figure it out
+ case special(uint8(c)):
+ p.token = string(c);
+ return;
+ case isdigit(uint8(c)):
+ for p.index < len(p.str) && isdigit(p.str[p.index]) {
+ p.index++
+ }
+ p.token = p.str[start : p.index];
+ return;
+ }
+ for p.index < len(p.str) && p.str[p.index] != ' ' && !special(p.str[p.index]) {
+ p.index++
+ }
+ p.token = p.str[start : p.index];
+}
+
+func (p *Parser) Type(name string) *StubType
+
+func (p *Parser) Array(name string) *StubType {
+ size := uint64(0);
+ open := true;
+ if p.token != "]" {
+ if len(p.token) == 0 || !isdigit(p.token[0]) {
+ return MissingStub
+ }
+ // write our own (trivial and simpleminded) atoi to avoid dependency
+ size = 0;
+ for i := 0; i < len(p.token); i++ {
+ size = size * 10 + uint64(p.token[i]) - '0'
+ }
+ p.Next();
+ open = false;
+ }
+ if p.token != "]" {
+ return MissingStub
+ }
+ p.Next();
+ elemtype := p.Type("");
+ return NewStubType(name, NewArrayTypeStruct(name, open, size, elemtype));
+}
+
+func (p *Parser) Map(name string) *StubType {
+ if p.token != "[" {
+ return MissingStub
+ }
+ p.Next();
+ keytype := p.Type("");
+ if p.token != "]" {
+ return MissingStub
+ }
+ p.Next();
+ elemtype := p.Type("");
+ return NewStubType(name, NewMapTypeStruct(name, keytype, elemtype));
+}
+
+func (p *Parser) Chan(name string, dir int) *StubType {
+ if p.token == "<-" {
+ if dir != BothDir {
+ return MissingStub
+ }
+ p.Next();
+ dir = SendDir;
+ }
+ elemtype := p.Type("");
+ return NewStubType(name, NewChanTypeStruct(name, dir, elemtype));
+}
+
+// Parse array of fields for struct, interface, and func arguments
+func (p *Parser) Fields(sep string) *[]Field {
+ a := new([]Field, 10);
+ nf := 0;
+ for p.token != "" && !special(p.token[0]) {
+ if nf == len(a) {
+ a1 := new([]Field, 2*nf);
+ for i := 0; i < nf; i++ {
+ a1[i] = a[i];
+ }
+ a = a1;
+ }
+ a[nf].name = p.token;
+ p.Next();
+ a[nf].typ = p.Type("");
+ nf++;
+ if p.token != sep {
+ break;
+ }
+ p.Next(); // skip separator
+ }
+ return a[0:nf];
+}
+
+func (p *Parser) Struct(name string) *StubType {
+ f := p.Fields(";");
+ if p.token != "}" {
+ return MissingStub;
+ }
+ p.Next();
+ return NewStubType(name, NewStructTypeStruct(name, f));
+}
+
+func (p *Parser) Interface(name string) *StubType {
+ f := p.Fields(";");
+ if p.token != "}" {
+ return MissingStub;
+ }
+ p.Next();
+ return NewStubType(name, NewInterfaceTypeStruct(name, f));
+}
+
+func (p *Parser) Func(name string) *StubType {
+ // may be 1 or 2 parenthesized lists
+ f1 := NewStructTypeStruct("", p.Fields(","));
+ if p.token != ")" {
+ return MissingStub;
+ }
+ p.Next();
+ if p.token != "(" {
+ // 1 list: the in parameters only
+ return NewStubType(name, NewFuncTypeStruct(name, f1, nil));
+ }
+ p.Next();
+ f2 := NewStructTypeStruct("", p.Fields(","));
+ if p.token != ")" {
+ return MissingStub;
+ }
+ p.Next();
+ // 2 lists: the in and out parameters are present
+ return NewStubType(name, NewFuncTypeStruct(name, f1, f2));
+}
+
+func (p *Parser) Type(name string) *StubType {
+ dir := BothDir;
+ switch {
+ case p.token == "":
+ return nil;
+ case p.token == "*":
+ p.Next();
+ return NewStubType(name, NewPtrTypeStruct(name, p.Type("")));
+ case p.token == "[":
+ p.Next();
+ return p.Array(name);
+ case p.token == "map":
+ p.Next();
+ return p.Map(name);
+ case p.token == "<-":
+ p.Next();
+ dir = RecvDir;
+ if p.token != "chan" {
+ return MissingStub;
+ }
+ fallthrough;
+ case p.token == "chan":
+ p.Next();
+ return p.Chan(name, dir);
+ case p.token == "struct":
+ p.Next();
+ if p.token != "{" {
+ return MissingStub
+ }
+ p.Next();
+ return p.Struct(name);
+ case p.token == "interface":
+ p.Next();
+ if p.token != "{" {
+ return MissingStub
+ }
+ p.Next();
+ return p.Interface(name);
+ case p.token == "(":
+ p.Next();
+ return p.Func(name);
+ case isdigit(p.token[0]):
+ p.Next();
+ return MissingStub;
+ case special(p.token[0]):
+ p.Next();
+ return MissingStub;
+ }
+ // must be an identifier. is it basic? if so, we have a stub
+ if s, ok := basicstub[p.token]; ok {
+ p.Next();
+ if name != "" {
+ // Need to make a copy because we are renaming a basic type
+ b := s.Get();
+ s = NewStubType(name, NewBasicType(name, b.Kind(), b.Size()));
+ }
+ return s
+ }
+ // not a basic - must be of the form "P.T"
+ ndot := 0;
+ for i := 0; i < len(p.token); i++ {
+ if p.token[i] == '.' {
+ ndot++
+ }
+ }
+ if ndot != 1 {
+ p.Next();
+ return MissingStub;
+ }
+ s := NewStubType(p.token, nil);
+ p.Next();
+ return s;
+}
+
+export func ParseTypeString(name, typestring string) Type {
+ p := new(Parser);
+ p.str = typestring;
+ p.Next();
+ return p.Type(name).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 := typestring[name];
+ if !ok {
+ InitializeTypeStrings();
+ s, ok = typestring[name];
+ if !ok {
+ s = MissingString;
+ typestring[name] = s;
+ }
+ }
+ return s
+}
+
+// Type is known by name. Find (and create if necessary) its real type.
+func ExpandType(name string) Type {
+ Lock();
+ t, ok := types[name];
+ if ok {
+ Unlock();
+ return *t
+ }
+ types[name] = &Missing; // prevent recursion; will overwrite
+ t1 := ParseTypeString(name, TypeNameToTypeString(name));
+ p := new(Type);
+ *p = t1;
+ types[name] = p;
+ Unlock();
+ return t1;
+}
diff --git a/src/lib/reflect/typestring.c b/src/lib/reflect/typestring.c
new file mode 100644
index 000000000..a5e6398ad
--- /dev/null
+++ b/src/lib/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/src/lib/reflect/value.go b/src/lib/reflect/value.go
new file mode 100644
index 000000000..a180b8140
--- /dev/null
+++ b/src/lib/reflect/value.go
@@ -0,0 +1,822 @@
+// 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 AddrToPtrInt8(Addr) *int8
+func AddrToPtrInt16(Addr) *int16
+func AddrToPtrInt32(Addr) *int32
+func AddrToPtrInt64(Addr) *int64
+func AddrToPtrUint8(Addr) *uint8
+func PtrUint8ToAddr(*uint8) Addr
+func AddrToPtrUint16(Addr) *uint16
+func AddrToPtrUint32(Addr) *uint32
+func AddrToPtrUint64(Addr) *uint64
+func PtrUint64ToAddr(*uint64) Addr
+func AddrToPtrFloat32(Addr) *float32
+func AddrToPtrFloat64(Addr) *float64
+func AddrToPtrFloat80(Addr) *float80
+func AddrToPtrString(Addr) *string
+
+// -- Int8
+
+export type Int8Value interface {
+ Kind() int;
+ Get() int8;
+ Put(int8);
+ Type() Type;
+}
+
+type Int8ValueStruct struct {
+ addr Addr
+}
+
+func (v *Int8ValueStruct) Kind() int {
+ return Int8Kind
+}
+
+func (v *Int8ValueStruct) Type() Type {
+ return Int8
+}
+
+func (v *Int8ValueStruct) Get() int8 {
+ return *AddrToPtrInt8(v.addr)
+}
+
+func (v *Int8ValueStruct) Put(i int8) {
+ *AddrToPtrInt8(v.addr) = i
+}
+
+func Int8Creator(typ Type, addr Addr) Value {
+ v := new(Int8ValueStruct);
+ v.addr = addr;
+ return v;
+}
+
+// -- Int16
+
+export type Int16Value interface {
+ Kind() int;
+ Get() int16;
+ Put(int16);
+ Type() Type;
+}
+
+type Int16ValueStruct struct {
+ addr Addr
+}
+
+func (v *Int16ValueStruct) Kind() int {
+ return Int16Kind
+}
+
+func (v *Int16ValueStruct) Type() Type {
+ return Int16
+}
+
+func (v *Int16ValueStruct) Get() int16 {
+ return *AddrToPtrInt16(v.addr)
+}
+
+func (v *Int16ValueStruct) Put(i int16) {
+ *AddrToPtrInt16(v.addr) = i
+}
+
+func Int16Creator(typ Type, addr Addr) Value {
+ v := new(Int16ValueStruct);
+ v.addr = addr;
+ return v;
+}
+
+// -- Int32
+
+export type Int32Value interface {
+ Kind() int;
+ Get() int32;
+ Put(int32);
+ Type() Type;
+}
+
+type Int32ValueStruct struct {
+ addr Addr
+}
+
+func (v *Int32ValueStruct) Type() Type {
+ return Int32
+}
+
+func (v *Int32ValueStruct) Kind() int {
+ return Int32Kind
+}
+
+func (v *Int32ValueStruct) Get() int32 {
+ return *AddrToPtrInt32(v.addr)
+}
+
+func (v *Int32ValueStruct) Put(i int32) {
+ *AddrToPtrInt32(v.addr) = i
+}
+
+func Int32Creator(typ Type, addr Addr) Value {
+ v := new(Int32ValueStruct);
+ v.addr = addr;
+ return v;
+}
+
+// -- Int64
+
+export type Int64Value interface {
+ Kind() int;
+ Get() int64;
+ Put(int64);
+ Type() Type;
+}
+
+type Int64ValueStruct struct {
+ addr Addr
+}
+
+func (v *Int64ValueStruct) Kind() int {
+ return Int64Kind
+}
+
+func (v *Int64ValueStruct) Type() Type {
+ return Int64
+}
+
+func (v *Int64ValueStruct) Get() int64 {
+ return *AddrToPtrInt64(v.addr)
+}
+
+func (v *Int64ValueStruct) Put(i int64) {
+ *AddrToPtrInt64(v.addr) = i
+}
+
+func Int64Creator(typ Type, addr Addr) Value {
+ v := new(Int64ValueStruct);
+ v.addr = addr;
+ return v;
+}
+
+// -- Uint8
+
+export type Uint8Value interface {
+ Kind() int;
+ Get() uint8;
+ Put(uint8);
+ Type() Type;
+}
+
+type Uint8ValueStruct struct {
+ addr Addr
+}
+
+func (v *Uint8ValueStruct) Kind() int {
+ return Uint8Kind
+}
+
+func (v *Uint8ValueStruct) Type() Type {
+ return Uint8
+}
+
+func (v *Uint8ValueStruct) Get() uint8 {
+ return *AddrToPtrUint8(v.addr)
+}
+
+func (v *Uint8ValueStruct) Put(i uint8) {
+ *AddrToPtrUint8(v.addr) = i
+}
+
+func Uint8Creator(typ Type, addr Addr) Value {
+ v := new(Uint8ValueStruct);
+ v.addr = addr;
+ return v;
+}
+
+// -- Uint16
+
+export type Uint16Value interface {
+ Kind() int;
+ Get() uint16;
+ Put(uint16);
+ Type() Type;
+}
+
+type Uint16ValueStruct struct {
+ addr Addr
+}
+
+func (v *Uint16ValueStruct) Kind() int {
+ return Uint16Kind
+}
+
+func (v *Uint16ValueStruct) Type() Type {
+ return Uint16
+}
+
+func (v *Uint16ValueStruct) Get() uint16 {
+ return *AddrToPtrUint16(v.addr)
+}
+
+func (v *Uint16ValueStruct) Put(i uint16) {
+ *AddrToPtrUint16(v.addr) = i
+}
+
+func Uint16Creator(typ Type, addr Addr) Value {
+ v := new(Uint16ValueStruct);
+ v.addr = addr;
+ return v;
+}
+
+// -- Uint32
+
+export type Uint32Value interface {
+ Kind() int;
+ Get() uint32;
+ Put(uint32);
+ Type() Type;
+}
+
+type Uint32ValueStruct struct {
+ addr Addr
+}
+
+func (v *Uint32ValueStruct) Kind() int {
+ return Uint32Kind
+}
+
+func (v *Uint32ValueStruct) Type() Type {
+ return Uint32
+}
+
+func (v *Uint32ValueStruct) Get() uint32 {
+ return *AddrToPtrUint32(v.addr)
+}
+
+func (v *Uint32ValueStruct) Put(i uint32) {
+ *AddrToPtrUint32(v.addr) = i
+}
+
+func Uint32Creator(typ Type, addr Addr) Value {
+ v := new(Uint32ValueStruct);
+ v.addr = addr;
+ return v;
+}
+
+// -- Uint64
+
+export type Uint64Value interface {
+ Kind() int;
+ Get() uint64;
+ Put(uint64);
+ Type() Type;
+}
+
+type Uint64ValueStruct struct {
+ addr Addr
+}
+
+func (v *Uint64ValueStruct) Kind() int {
+ return Uint64Kind
+}
+
+func (v *Uint64ValueStruct) Type() Type {
+ return Uint64
+}
+
+func (v *Uint64ValueStruct) Get() uint64 {
+ return *AddrToPtrUint64(v.addr)
+}
+
+func (v *Uint64ValueStruct) Put(i uint64) {
+ *AddrToPtrUint64(v.addr) = i
+}
+
+func Uint64Creator(typ Type, addr Addr) Value {
+ v := new(Uint64ValueStruct);
+ v.addr = addr;
+ return v;
+}
+
+// -- Float32
+
+export type Float32Value interface {
+ Kind() int;
+ Get() float32;
+ Put(float32);
+ Type() Type;
+}
+
+type Float32ValueStruct struct {
+ addr Addr
+}
+
+func (v *Float32ValueStruct) Kind() int {
+ return Float32Kind
+}
+
+func (v *Float32ValueStruct) Type() Type {
+ return Float32
+}
+
+func (v *Float32ValueStruct) Get() float32 {
+ return *AddrToPtrFloat32(v.addr)
+}
+
+func (v *Float32ValueStruct) Put(f float32) {
+ *AddrToPtrFloat32(v.addr) = f
+}
+
+func Float32Creator(typ Type, addr Addr) Value {
+ v := new(Float32ValueStruct);
+ v.addr = addr;
+ return v;
+}
+
+// -- Float64
+
+export type Float64Value interface {
+ Kind() int;
+ Get() float64;
+ Put(float64);
+ Type() Type;
+}
+
+type Float64ValueStruct struct {
+ addr Addr
+}
+
+func (v *Float64ValueStruct) Kind() int {
+ return Float64Kind
+}
+
+func (v *Float64ValueStruct) Type() Type {
+ return Float64
+}
+
+func (v *Float64ValueStruct) Get() float64 {
+ return *AddrToPtrFloat64(v.addr)
+}
+
+func (v *Float64ValueStruct) Put(f float64) {
+ *AddrToPtrFloat64(v.addr) = f
+}
+
+func Float64Creator(typ Type, addr Addr) Value {
+ v := new(Float64ValueStruct);
+ v.addr = addr;
+ return v;
+}
+
+// -- Float80
+
+export type Float80Value interface {
+ Kind() int;
+ Get() float80;
+ Put(float80);
+ Type() Type;
+}
+
+type Float80ValueStruct struct {
+ addr Addr
+}
+
+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 *AddrToPtrFloat80(v.addr)
+ return 0;
+}
+
+func (v *Float80ValueStruct) Put(f float80) {
+ *AddrToPtrFloat80(v.addr) = f
+}
+*/
+
+func Float80Creator(typ Type, addr Addr) Value {
+ v := new(Float80ValueStruct);
+ v.addr = addr;
+ return v;
+}
+
+// -- String
+
+export type StringValue interface {
+ Kind() int;
+ Get() string;
+ Put(string);
+ Type() Type;
+}
+
+type StringValueStruct struct {
+ addr Addr
+}
+
+func (v *StringValueStruct) Kind() int {
+ return StringKind
+}
+
+func (v *StringValueStruct) Type() Type {
+ return String
+}
+
+func (v *StringValueStruct) Get() string {
+ return *AddrToPtrString(v.addr)
+}
+
+func (v *StringValueStruct) Put(s string) {
+ *AddrToPtrString(v.addr) = s
+}
+
+func StringCreator(typ Type, addr Addr) Value {
+ v := new(StringValueStruct);
+ v.addr = addr;
+ return v;
+}
+
+// -- Pointer
+
+export type PtrValue interface {
+ Kind() int;
+ Sub() Value;
+ Type() Type;
+ Indirect() Addr;
+}
+
+type PtrValueStruct struct {
+ addr Addr;
+ typ Type;
+}
+
+func (v *PtrValueStruct) Kind() int {
+ return PtrKind
+}
+
+func (v *PtrValueStruct) Type() Type {
+ return v.typ
+}
+
+func (v *PtrValueStruct) Indirect() Addr {
+ return *AddrToPtrAddr(v.addr)
+}
+
+func (v *PtrValueStruct) Sub() Value {
+ return NewValueAddr(v.typ.(PtrType).Sub(), v.Indirect());
+}
+
+func PtrCreator(typ Type, addr Addr) Value {
+ return &PtrValueStruct{addr, typ};
+}
+
+// -- Array TODO: finish and test
+
+export type ArrayValue interface {
+ Kind() int;
+ Type() Type;
+ Open() bool;
+ Len() uint64;
+ Elem(i uint64) Value;
+}
+
+type OpenArrayValueStruct struct {
+ addr Addr;
+ typ Type;
+ elemtype Type;
+ elemsize uint64;
+}
+/*
+ Run-time representation of open arrays looks like this:
+ struct Array {
+ byte* array; // actual data
+ uint32 nel; // number of elements
+ };
+*/
+
+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() uint64 {
+ return uint64(*AddrToPtrInt32(v.addr+8));
+}
+
+func (v *OpenArrayValueStruct) Elem(i uint64) Value {
+ base := *AddrToPtrAddr(v.addr);
+ return NewValueAddr(v.elemtype, base + i * v.elemsize);
+}
+
+type FixedArrayValueStruct struct {
+ addr Addr;
+ typ Type;
+ elemtype Type;
+ elemsize uint64;
+ len 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() uint64 {
+ return v.len
+}
+
+func (v *FixedArrayValueStruct) Elem(i uint64) Value {
+ return NewValueAddr(v.elemtype, v.addr + i * v.elemsize);
+ return nil
+}
+
+func ArrayCreator(typ Type, addr Addr) Value {
+ arraytype := typ.(ArrayType);
+ if arraytype.Open() {
+ v := new(OpenArrayValueStruct);
+ v.addr = addr;
+ v.typ = typ;
+ v.elemtype = arraytype.Elem();
+ v.elemsize = v.elemtype.Size();
+ return v;
+ }
+ v := new(FixedArrayValueStruct);
+ v.addr = addr;
+ v.typ = typ;
+ v.elemtype = arraytype.Elem();
+ v.elemsize = v.elemtype.Size();
+ v.len = 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 {
+ addr 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.addr = addr;
+ v.typ = typ;
+ return v;
+}
+
+// -- Chan
+
+export type ChanValue interface {
+ Kind() int;
+ Type() Type;
+}
+
+type ChanValueStruct struct {
+ addr 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.addr = addr;
+ v.typ = typ;
+ return v;
+}
+
+// -- Struct
+
+export type StructValue interface {
+ Kind() int;
+ Type() Type;
+ Len() int;
+ Field(i int) Value;
+}
+
+type StructValueStruct struct {
+ addr Addr;
+ 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);
+ v.addr = addr;
+ 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 {
+ addr 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.addr = addr;
+ v.typ = typ;
+ return v;
+}
+
+// -- Func
+
+export type FuncValue interface {
+ Kind() int;
+ Type() Type;
+}
+
+type FuncValueFunc struct {
+ addr 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.addr = 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);
+}
+
+export func NewInitValue(typ Type) Value {
+ // Some values cannot be made this way.
+ switch typ.Kind() {
+ case FuncKind, ChanKind, MapKind: // must be pointers, at least for now (TODO?)
+ return nil;
+ case ArrayKind:
+ if typ.(ArrayType).Open() {
+ return nil
+ }
+ }
+ size := typ.Size();
+ if size == 0 {
+ size = 1;
+ }
+ data := new([]uint8, size);
+ return NewValueAddr(typ, PtrUint8ToAddr(&data[0]));
+}
+
+export type Empty interface {}
+
+export func NewValue(e Empty) Value {
+ value, typestring := sys.reflect(e);
+ typ := ParseTypeString("", typestring);
+ // Content of interface is a value; need a permanent copy to take its address
+ // so we can modify the contents. Values contain pointers to 'values'.
+ ap := new(uint64);
+ *ap = value;
+ return NewValueAddr(typ, PtrUint64ToAddr(ap));
+}